feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,561 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Point2D;
import java.awt.AlphaComposite;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.lang.annotation.Native;
import sun.awt.image.ImagingLib;
/**
* This class uses an affine transform to perform a linear mapping from
* 2D coordinates in the source image or <CODE>Raster</CODE> to 2D coordinates
* in the destination image or <CODE>Raster</CODE>.
* The type of interpolation that is used is specified through a constructor,
* either by a <CODE>RenderingHints</CODE> object or by one of the integer
* interpolation types defined in this class.
* <p>
* If a <CODE>RenderingHints</CODE> object is specified in the constructor, the
* interpolation hint and the rendering quality hint are used to set
* the interpolation type for this operation. The color rendering hint
* and the dithering hint can be used when color conversion is required.
* <p>
* Note that the following constraints have to be met:
* <ul>
* <li>The source and destination must be different.
* <li>For <CODE>Raster</CODE> objects, the number of bands in the source must
* be equal to the number of bands in the destination.
* </ul>
* @see AffineTransform
* @see BufferedImageFilter
* @see java.awt.RenderingHints#KEY_INTERPOLATION
* @see java.awt.RenderingHints#KEY_RENDERING
* @see java.awt.RenderingHints#KEY_COLOR_RENDERING
* @see java.awt.RenderingHints#KEY_DITHERING
*/
public class AffineTransformOp implements BufferedImageOp, RasterOp {
private AffineTransform xform;
RenderingHints hints;
/**
* Nearest-neighbor interpolation type.
*/
@Native public static final int TYPE_NEAREST_NEIGHBOR = 1;
/**
* Bilinear interpolation type.
*/
@Native public static final int TYPE_BILINEAR = 2;
/**
* Bicubic interpolation type.
*/
@Native public static final int TYPE_BICUBIC = 3;
int interpolationType = TYPE_NEAREST_NEIGHBOR;
/**
* Constructs an <CODE>AffineTransformOp</CODE> given an affine transform.
* The interpolation type is determined from the
* <CODE>RenderingHints</CODE> object. If the interpolation hint is
* defined, it will be used. Otherwise, if the rendering quality hint is
* defined, the interpolation type is determined from its value. If no
* hints are specified (<CODE>hints</CODE> is null),
* the interpolation type is {@link #TYPE_NEAREST_NEIGHBOR
* TYPE_NEAREST_NEIGHBOR}.
*
* @param xform The <CODE>AffineTransform</CODE> to use for the
* operation.
*
* @param hints The <CODE>RenderingHints</CODE> object used to specify
* the interpolation type for the operation.
*
* @throws ImagingOpException if the transform is non-invertible.
* @see java.awt.RenderingHints#KEY_INTERPOLATION
* @see java.awt.RenderingHints#KEY_RENDERING
*/
public AffineTransformOp(AffineTransform xform, RenderingHints hints){
validateTransform(xform);
this.xform = (AffineTransform) xform.clone();
this.hints = hints;
if (hints != null) {
Object value = hints.get(hints.KEY_INTERPOLATION);
if (value == null) {
value = hints.get(hints.KEY_RENDERING);
if (value == hints.VALUE_RENDER_SPEED) {
interpolationType = TYPE_NEAREST_NEIGHBOR;
}
else if (value == hints.VALUE_RENDER_QUALITY) {
interpolationType = TYPE_BILINEAR;
}
}
else if (value == hints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR) {
interpolationType = TYPE_NEAREST_NEIGHBOR;
}
else if (value == hints.VALUE_INTERPOLATION_BILINEAR) {
interpolationType = TYPE_BILINEAR;
}
else if (value == hints.VALUE_INTERPOLATION_BICUBIC) {
interpolationType = TYPE_BICUBIC;
}
}
else {
interpolationType = TYPE_NEAREST_NEIGHBOR;
}
}
/**
* Constructs an <CODE>AffineTransformOp</CODE> given an affine transform
* and the interpolation type.
*
* @param xform The <CODE>AffineTransform</CODE> to use for the operation.
* @param interpolationType One of the integer
* interpolation type constants defined by this class:
* {@link #TYPE_NEAREST_NEIGHBOR TYPE_NEAREST_NEIGHBOR},
* {@link #TYPE_BILINEAR TYPE_BILINEAR},
* {@link #TYPE_BICUBIC TYPE_BICUBIC}.
* @throws ImagingOpException if the transform is non-invertible.
*/
public AffineTransformOp(AffineTransform xform, int interpolationType) {
validateTransform(xform);
this.xform = (AffineTransform)xform.clone();
switch(interpolationType) {
case TYPE_NEAREST_NEIGHBOR:
case TYPE_BILINEAR:
case TYPE_BICUBIC:
break;
default:
throw new IllegalArgumentException("Unknown interpolation type: "+
interpolationType);
}
this.interpolationType = interpolationType;
}
/**
* Returns the interpolation type used by this op.
* @return the interpolation type.
* @see #TYPE_NEAREST_NEIGHBOR
* @see #TYPE_BILINEAR
* @see #TYPE_BICUBIC
*/
public final int getInterpolationType() {
return interpolationType;
}
/**
* Transforms the source <CODE>BufferedImage</CODE> and stores the results
* in the destination <CODE>BufferedImage</CODE>.
* If the color models for the two images do not match, a color
* conversion into the destination color model is performed.
* If the destination image is null,
* a <CODE>BufferedImage</CODE> is created with the source
* <CODE>ColorModel</CODE>.
* <p>
* The coordinates of the rectangle returned by
* <code>getBounds2D(BufferedImage)</code>
* are not necessarily the same as the coordinates of the
* <code>BufferedImage</code> returned by this method. If the
* upper-left corner coordinates of the rectangle are
* negative then this part of the rectangle is not drawn. If the
* upper-left corner coordinates of the rectangle are positive
* then the filtered image is drawn at that position in the
* destination <code>BufferedImage</code>.
* <p>
* An <CODE>IllegalArgumentException</CODE> is thrown if the source is
* the same as the destination.
*
* @param src The <CODE>BufferedImage</CODE> to transform.
* @param dst The <CODE>BufferedImage</CODE> in which to store the results
* of the transformation.
*
* @return The filtered <CODE>BufferedImage</CODE>.
* @throws IllegalArgumentException if <code>src</code> and
* <code>dst</code> are the same
* @throws ImagingOpException if the image cannot be transformed
* because of a data-processing error that might be
* caused by an invalid image format, tile format, or
* image-processing operation, or any other unsupported
* operation.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
if (src == null) {
throw new NullPointerException("src image is null");
}
if (src == dst) {
throw new IllegalArgumentException("src image cannot be the "+
"same as the dst image");
}
boolean needToConvert = false;
ColorModel srcCM = src.getColorModel();
ColorModel dstCM;
BufferedImage origDst = dst;
if (dst == null) {
dst = createCompatibleDestImage(src, null);
dstCM = srcCM;
origDst = dst;
}
else {
dstCM = dst.getColorModel();
if (srcCM.getColorSpace().getType() !=
dstCM.getColorSpace().getType())
{
int type = xform.getType();
boolean needTrans = ((type&
(xform.TYPE_MASK_ROTATION|
xform.TYPE_GENERAL_TRANSFORM))
!= 0);
if (! needTrans && type != xform.TYPE_TRANSLATION && type != xform.TYPE_IDENTITY)
{
double[] mtx = new double[4];
xform.getMatrix(mtx);
// Check out the matrix. A non-integral scale will force ARGB
// since the edge conditions can't be guaranteed.
needTrans = (mtx[0] != (int)mtx[0] || mtx[3] != (int)mtx[3]);
}
if (needTrans &&
srcCM.getTransparency() == Transparency.OPAQUE)
{
// Need to convert first
ColorConvertOp ccop = new ColorConvertOp(hints);
BufferedImage tmpSrc = null;
int sw = src.getWidth();
int sh = src.getHeight();
if (dstCM.getTransparency() == Transparency.OPAQUE) {
tmpSrc = new BufferedImage(sw, sh,
BufferedImage.TYPE_INT_ARGB);
}
else {
WritableRaster r =
dstCM.createCompatibleWritableRaster(sw, sh);
tmpSrc = new BufferedImage(dstCM, r,
dstCM.isAlphaPremultiplied(),
null);
}
src = ccop.filter(src, tmpSrc);
}
else {
needToConvert = true;
dst = createCompatibleDestImage(src, null);
}
}
}
if (interpolationType != TYPE_NEAREST_NEIGHBOR &&
dst.getColorModel() instanceof IndexColorModel) {
dst = new BufferedImage(dst.getWidth(), dst.getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
if (ImagingLib.filter(this, src, dst) == null) {
throw new ImagingOpException ("Unable to transform src image");
}
if (needToConvert) {
ColorConvertOp ccop = new ColorConvertOp(hints);
ccop.filter(dst, origDst);
}
else if (origDst != dst) {
java.awt.Graphics2D g = origDst.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(dst, 0, 0, null);
} finally {
g.dispose();
}
}
return origDst;
}
/**
* Transforms the source <CODE>Raster</CODE> and stores the results in
* the destination <CODE>Raster</CODE>. This operation performs the
* transform band by band.
* <p>
* If the destination <CODE>Raster</CODE> is null, a new
* <CODE>Raster</CODE> is created.
* An <CODE>IllegalArgumentException</CODE> may be thrown if the source is
* the same as the destination or if the number of bands in
* the source is not equal to the number of bands in the
* destination.
* <p>
* The coordinates of the rectangle returned by
* <code>getBounds2D(Raster)</code>
* are not necessarily the same as the coordinates of the
* <code>WritableRaster</code> returned by this method. If the
* upper-left corner coordinates of rectangle are negative then
* this part of the rectangle is not drawn. If the coordinates
* of the rectangle are positive then the filtered image is drawn at
* that position in the destination <code>Raster</code>.
* <p>
* @param src The <CODE>Raster</CODE> to transform.
* @param dst The <CODE>Raster</CODE> in which to store the results of the
* transformation.
*
* @return The transformed <CODE>Raster</CODE>.
*
* @throws ImagingOpException if the raster cannot be transformed
* because of a data-processing error that might be
* caused by an invalid image format, tile format, or
* image-processing operation, or any other unsupported
* operation.
*/
public final WritableRaster filter(Raster src, WritableRaster dst) {
if (src == null) {
throw new NullPointerException("src image is null");
}
if (dst == null) {
dst = createCompatibleDestRaster(src);
}
if (src == dst) {
throw new IllegalArgumentException("src image cannot be the "+
"same as the dst image");
}
if (src.getNumBands() != dst.getNumBands()) {
throw new IllegalArgumentException("Number of src bands ("+
src.getNumBands()+
") does not match number of "+
" dst bands ("+
dst.getNumBands()+")");
}
if (ImagingLib.filter(this, src, dst) == null) {
throw new ImagingOpException ("Unable to transform src image");
}
return dst;
}
/**
* Returns the bounding box of the transformed destination. The
* rectangle returned is the actual bounding box of the
* transformed points. The coordinates of the upper-left corner
* of the returned rectangle might not be (0,&nbsp;0).
*
* @param src The <CODE>BufferedImage</CODE> to be transformed.
*
* @return The <CODE>Rectangle2D</CODE> representing the destination's
* bounding box.
*/
public final Rectangle2D getBounds2D (BufferedImage src) {
return getBounds2D(src.getRaster());
}
/**
* Returns the bounding box of the transformed destination. The
* rectangle returned will be the actual bounding box of the
* transformed points. The coordinates of the upper-left corner
* of the returned rectangle might not be (0,&nbsp;0).
*
* @param src The <CODE>Raster</CODE> to be transformed.
*
* @return The <CODE>Rectangle2D</CODE> representing the destination's
* bounding box.
*/
public final Rectangle2D getBounds2D (Raster src) {
int w = src.getWidth();
int h = src.getHeight();
// Get the bounding box of the src and transform the corners
float[] pts = {0, 0, w, 0, w, h, 0, h};
xform.transform(pts, 0, pts, 0, 4);
// Get the min, max of the dst
float fmaxX = pts[0];
float fmaxY = pts[1];
float fminX = pts[0];
float fminY = pts[1];
for (int i=2; i < 8; i+=2) {
if (pts[i] > fmaxX) {
fmaxX = pts[i];
}
else if (pts[i] < fminX) {
fminX = pts[i];
}
if (pts[i+1] > fmaxY) {
fmaxY = pts[i+1];
}
else if (pts[i+1] < fminY) {
fminY = pts[i+1];
}
}
return new Rectangle2D.Float(fminX, fminY, fmaxX-fminX, fmaxY-fminY);
}
/**
* Creates a zeroed destination image with the correct size and number of
* bands. A <CODE>RasterFormatException</CODE> may be thrown if the
* transformed width or height is equal to 0.
* <p>
* If <CODE>destCM</CODE> is null,
* an appropriate <CODE>ColorModel</CODE> is used; this
* <CODE>ColorModel</CODE> may have
* an alpha channel even if the source <CODE>ColorModel</CODE> is opaque.
*
* @param src The <CODE>BufferedImage</CODE> to be transformed.
* @param destCM <CODE>ColorModel</CODE> of the destination. If null,
* an appropriate <CODE>ColorModel</CODE> is used.
*
* @return The zeroed destination image.
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM) {
BufferedImage image;
Rectangle r = getBounds2D(src).getBounds();
// If r.x (or r.y) is < 0, then we want to only create an image
// that is in the positive range.
// If r.x (or r.y) is > 0, then we need to create an image that
// includes the translation.
int w = r.x + r.width;
int h = r.y + r.height;
if (w <= 0) {
throw new RasterFormatException("Transformed width ("+w+
") is less than or equal to 0.");
}
if (h <= 0) {
throw new RasterFormatException("Transformed height ("+h+
") is less than or equal to 0.");
}
if (destCM == null) {
ColorModel cm = src.getColorModel();
if (interpolationType != TYPE_NEAREST_NEIGHBOR &&
(cm instanceof IndexColorModel ||
cm.getTransparency() == Transparency.OPAQUE))
{
image = new BufferedImage(w, h,
BufferedImage.TYPE_INT_ARGB);
}
else {
image = new BufferedImage(cm,
src.getRaster().createCompatibleWritableRaster(w,h),
cm.isAlphaPremultiplied(), null);
}
}
else {
image = new BufferedImage(destCM,
destCM.createCompatibleWritableRaster(w,h),
destCM.isAlphaPremultiplied(), null);
}
return image;
}
/**
* Creates a zeroed destination <CODE>Raster</CODE> with the correct size
* and number of bands. A <CODE>RasterFormatException</CODE> may be thrown
* if the transformed width or height is equal to 0.
*
* @param src The <CODE>Raster</CODE> to be transformed.
*
* @return The zeroed destination <CODE>Raster</CODE>.
*/
public WritableRaster createCompatibleDestRaster (Raster src) {
Rectangle2D r = getBounds2D(src);
return src.createCompatibleWritableRaster((int)r.getX(),
(int)r.getY(),
(int)r.getWidth(),
(int)r.getHeight());
}
/**
* Returns the location of the corresponding destination point given a
* point in the source. If <CODE>dstPt</CODE> is specified, it
* is used to hold the return value.
*
* @param srcPt The <code>Point2D</code> that represents the source
* point.
* @param dstPt The <CODE>Point2D</CODE> in which to store the result.
*
* @return The <CODE>Point2D</CODE> in the destination that corresponds to
* the specified point in the source.
*/
public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
return xform.transform (srcPt, dstPt);
}
/**
* Returns the affine transform used by this transform operation.
*
* @return The <CODE>AffineTransform</CODE> associated with this op.
*/
public final AffineTransform getTransform() {
return (AffineTransform) xform.clone();
}
/**
* Returns the rendering hints used by this transform operation.
*
* @return The <CODE>RenderingHints</CODE> object associated with this op.
*/
public final RenderingHints getRenderingHints() {
if (hints == null) {
Object val;
switch(interpolationType) {
case TYPE_NEAREST_NEIGHBOR:
val = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
break;
case TYPE_BILINEAR:
val = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
break;
case TYPE_BICUBIC:
val = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
break;
default:
// Should never get here
throw new InternalError("Unknown interpolation type "+
interpolationType);
}
hints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, val);
}
return hints;
}
// We need to be able to invert the transform if we want to
// transform the image. If the determinant of the matrix is 0,
// then we can't invert the transform.
void validateTransform(AffineTransform xform) {
if (Math.abs(xform.getDeterminant()) <= Double.MIN_VALUE) {
throw new ImagingOpException("Unable to invert transform "+xform);
}
}
}

View File

@@ -0,0 +1,281 @@
/*
* Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
import java.util.Hashtable;
import java.awt.Rectangle;
/**
* An ImageFilter class for scaling images using a simple area averaging
* algorithm that produces smoother results than the nearest neighbor
* algorithm.
* <p>This class extends the basic ImageFilter Class to scale an existing
* image and provide a source for a new image containing the resampled
* image. The pixels in the source image are blended to produce pixels
* for an image of the specified size. The blending process is analogous
* to scaling up the source image to a multiple of the destination size
* using pixel replication and then scaling it back down to the destination
* size by simply averaging all the pixels in the supersized image that
* fall within a given pixel of the destination image. If the data from
* the source is not delivered in TopDownLeftRight order then the filter
* will back off to a simple pixel replication behavior and utilize the
* requestTopDownLeftRightResend() method to refilter the pixels in a
* better way at the end.
* <p>It is meant to be used in conjunction with a FilteredImageSource
* object to produce scaled versions of existing images. Due to
* implementation dependencies, there may be differences in pixel values
* of an image filtered on different platforms.
*
* @see FilteredImageSource
* @see ReplicateScaleFilter
* @see ImageFilter
*
* @author Jim Graham
*/
public class AreaAveragingScaleFilter extends ReplicateScaleFilter {
private static final ColorModel rgbmodel = ColorModel.getRGBdefault();
private static final int neededHints = (TOPDOWNLEFTRIGHT
| COMPLETESCANLINES);
private boolean passthrough;
private float reds[], greens[], blues[], alphas[];
private int savedy;
private int savedyrem;
/**
* Constructs an AreaAveragingScaleFilter that scales the pixels from
* its source Image as specified by the width and height parameters.
* @param width the target width to scale the image
* @param height the target height to scale the image
*/
public AreaAveragingScaleFilter(int width, int height) {
super(width, height);
}
/**
* Detect if the data is being delivered with the necessary hints
* to allow the averaging algorithm to do its work.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose
* pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#setHints
*/
public void setHints(int hints) {
passthrough = ((hints & neededHints) != neededHints);
super.setHints(hints);
}
private void makeAccumBuffers() {
reds = new float[destWidth];
greens = new float[destWidth];
blues = new float[destWidth];
alphas = new float[destWidth];
}
private int[] calcRow() {
float origmult = ((float) srcWidth) * srcHeight;
if (outpixbuf == null || !(outpixbuf instanceof int[])) {
outpixbuf = new int[destWidth];
}
int[] outpix = (int[]) outpixbuf;
for (int x = 0; x < destWidth; x++) {
float mult = origmult;
int a = Math.round(alphas[x] / mult);
if (a <= 0) {
a = 0;
} else if (a >= 255) {
a = 255;
} else {
// un-premultiply the components (by modifying mult here, we
// are effectively doing the divide by mult and divide by
// alpha in the same step)
mult = alphas[x] / 255;
}
int r = Math.round(reds[x] / mult);
int g = Math.round(greens[x] / mult);
int b = Math.round(blues[x] / mult);
if (r < 0) {r = 0;} else if (r > 255) {r = 255;}
if (g < 0) {g = 0;} else if (g > 255) {g = 255;}
if (b < 0) {b = 0;} else if (b > 255) {b = 255;}
outpix[x] = (a << 24 | r << 16 | g << 8 | b);
}
return outpix;
}
private void accumPixels(int x, int y, int w, int h,
ColorModel model, Object pixels, int off,
int scansize) {
if (reds == null) {
makeAccumBuffers();
}
int sy = y;
int syrem = destHeight;
int dy, dyrem;
if (sy == 0) {
dy = 0;
dyrem = 0;
} else {
dy = savedy;
dyrem = savedyrem;
}
while (sy < y + h) {
int amty;
if (dyrem == 0) {
for (int i = 0; i < destWidth; i++) {
alphas[i] = reds[i] = greens[i] = blues[i] = 0f;
}
dyrem = srcHeight;
}
if (syrem < dyrem) {
amty = syrem;
} else {
amty = dyrem;
}
int sx = 0;
int dx = 0;
int sxrem = 0;
int dxrem = srcWidth;
float a = 0f, r = 0f, g = 0f, b = 0f;
while (sx < w) {
if (sxrem == 0) {
sxrem = destWidth;
int rgb;
if (pixels instanceof byte[]) {
rgb = ((byte[]) pixels)[off + sx] & 0xff;
} else {
rgb = ((int[]) pixels)[off + sx];
}
// getRGB() always returns non-premultiplied components
rgb = model.getRGB(rgb);
a = rgb >>> 24;
r = (rgb >> 16) & 0xff;
g = (rgb >> 8) & 0xff;
b = rgb & 0xff;
// premultiply the components if necessary
if (a != 255.0f) {
float ascale = a / 255.0f;
r *= ascale;
g *= ascale;
b *= ascale;
}
}
int amtx;
if (sxrem < dxrem) {
amtx = sxrem;
} else {
amtx = dxrem;
}
float mult = ((float) amtx) * amty;
alphas[dx] += mult * a;
reds[dx] += mult * r;
greens[dx] += mult * g;
blues[dx] += mult * b;
if ((sxrem -= amtx) == 0) {
sx++;
}
if ((dxrem -= amtx) == 0) {
dx++;
dxrem = srcWidth;
}
}
if ((dyrem -= amty) == 0) {
int outpix[] = calcRow();
do {
consumer.setPixels(0, dy, destWidth, 1,
rgbmodel, outpix, 0, destWidth);
dy++;
} while ((syrem -= amty) >= amty && amty == srcHeight);
} else {
syrem -= amty;
}
if (syrem == 0) {
syrem = destHeight;
sy++;
off += scansize;
}
}
savedyrem = dyrem;
savedy = dy;
}
/**
* Combine the components for the delivered byte pixels into the
* accumulation arrays and send on any averaged data for rows of
* pixels that are complete. If the correct hints were not
* specified in the setHints call then relay the work to our
* superclass which is capable of scaling pixels regardless of
* the delivery hints.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code>
* whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ReplicateScaleFilter
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off,
int scansize) {
if (passthrough) {
super.setPixels(x, y, w, h, model, pixels, off, scansize);
} else {
accumPixels(x, y, w, h, model, pixels, off, scansize);
}
}
/**
* Combine the components for the delivered int pixels into the
* accumulation arrays and send on any averaged data for rows of
* pixels that are complete. If the correct hints were not
* specified in the setHints call then relay the work to our
* superclass which is capable of scaling pixels regardless of
* the delivery hints.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code>
* whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ReplicateScaleFilter
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off,
int scansize) {
if (passthrough) {
super.setPixels(x, y, w, h, model, pixels, off, scansize);
} else {
accumPixels(x, y, w, h, model, pixels, off, scansize);
}
}
}

View File

@@ -0,0 +1,289 @@
/*
* Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.GraphicsEnvironment;
import java.awt.color.ICC_Profile;
import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.RenderingHints;
import sun.awt.image.ImagingLib;
import java.util.Arrays;
/**
* This class performs an arbitrary linear combination of the bands
* in a <CODE>Raster</CODE>, using a specified matrix.
* <p>
* The width of the matrix must be equal to the number of bands in the
* source <CODE>Raster</CODE>, optionally plus one. If there is one more
* column in the matrix than the number of bands, there is an implied 1 at the
* end of the vector of band samples representing a pixel. The height
* of the matrix must be equal to the number of bands in the destination.
* <p>
* For example, a 3-banded <CODE>Raster</CODE> might have the following
* transformation applied to each pixel in order to invert the second band of
* the <CODE>Raster</CODE>.
* <pre>
* [ 1.0 0.0 0.0 0.0 ] [ b1 ]
* [ 0.0 -1.0 0.0 255.0 ] x [ b2 ]
* [ 0.0 0.0 1.0 0.0 ] [ b3 ]
* [ 1 ]
* </pre>
*
* <p>
* Note that the source and destination can be the same object.
*/
public class BandCombineOp implements RasterOp {
float[][] matrix;
int nrows = 0;
int ncols = 0;
RenderingHints hints;
/**
* Constructs a <CODE>BandCombineOp</CODE> with the specified matrix.
* The width of the matrix must be equal to the number of bands in
* the source <CODE>Raster</CODE>, optionally plus one. If there is one
* more column in the matrix than the number of bands, there is an implied
* 1 at the end of the vector of band samples representing a pixel. The
* height of the matrix must be equal to the number of bands in the
* destination.
* <p>
* The first subscript is the row index and the second
* is the column index. This operation uses none of the currently
* defined rendering hints; the <CODE>RenderingHints</CODE> argument can be
* null.
*
* @param matrix The matrix to use for the band combine operation.
* @param hints The <CODE>RenderingHints</CODE> object for this operation.
* Not currently used so it can be null.
*/
public BandCombineOp (float[][] matrix, RenderingHints hints) {
nrows = matrix.length;
ncols = matrix[0].length;
this.matrix = new float[nrows][];
for (int i=0; i < nrows; i++) {
/* Arrays.copyOf is forgiving of the source array being
* too short, but it is also faster than other cloning
* methods, so we provide our own protection for short
* matrix rows.
*/
if (ncols > matrix[i].length) {
throw new IndexOutOfBoundsException("row "+i+" too short");
}
this.matrix[i] = Arrays.copyOf(matrix[i], ncols);
}
this.hints = hints;
}
/**
* Returns a copy of the linear combination matrix.
*
* @return The matrix associated with this band combine operation.
*/
public final float[][] getMatrix() {
float[][] ret = new float[nrows][];
for (int i = 0; i < nrows; i++) {
ret[i] = Arrays.copyOf(matrix[i], ncols);
}
return ret;
}
/**
* Transforms the <CODE>Raster</CODE> using the matrix specified in the
* constructor. An <CODE>IllegalArgumentException</CODE> may be thrown if
* the number of bands in the source or destination is incompatible with
* the matrix. See the class comments for more details.
* <p>
* If the destination is null, it will be created with a number of bands
* equalling the number of rows in the matrix. No exception is thrown
* if the operation causes a data overflow.
*
* @param src The <CODE>Raster</CODE> to be filtered.
* @param dst The <CODE>Raster</CODE> in which to store the results
* of the filter operation.
*
* @return The filtered <CODE>Raster</CODE>.
*
* @throws IllegalArgumentException If the number of bands in the
* source or destination is incompatible with the matrix.
*/
public WritableRaster filter(Raster src, WritableRaster dst) {
int nBands = src.getNumBands();
if (ncols != nBands && ncols != (nBands+1)) {
throw new IllegalArgumentException("Number of columns in the "+
"matrix ("+ncols+
") must be equal to the number"+
" of bands ([+1]) in src ("+
nBands+").");
}
if (dst == null) {
dst = createCompatibleDestRaster(src);
}
else if (nrows != dst.getNumBands()) {
throw new IllegalArgumentException("Number of rows in the "+
"matrix ("+nrows+
") must be equal to the number"+
" of bands ([+1]) in dst ("+
nBands+").");
}
if (ImagingLib.filter(this, src, dst) != null) {
return dst;
}
int[] pixel = null;
int[] dstPixel = new int[dst.getNumBands()];
float accum;
int sminX = src.getMinX();
int sY = src.getMinY();
int dminX = dst.getMinX();
int dY = dst.getMinY();
int sX;
int dX;
if (ncols == nBands) {
for (int y=0; y < src.getHeight(); y++, sY++, dY++) {
dX = dminX;
sX = sminX;
for (int x=0; x < src.getWidth(); x++, sX++, dX++) {
pixel = src.getPixel(sX, sY, pixel);
for (int r=0; r < nrows; r++) {
accum = 0.f;
for (int c=0; c < ncols; c++) {
accum += matrix[r][c]*pixel[c];
}
dstPixel[r] = (int) accum;
}
dst.setPixel(dX, dY, dstPixel);
}
}
}
else {
// Need to add constant
for (int y=0; y < src.getHeight(); y++, sY++, dY++) {
dX = dminX;
sX = sminX;
for (int x=0; x < src.getWidth(); x++, sX++, dX++) {
pixel = src.getPixel(sX, sY, pixel);
for (int r=0; r < nrows; r++) {
accum = 0.f;
for (int c=0; c < nBands; c++) {
accum += matrix[r][c]*pixel[c];
}
dstPixel[r] = (int) (accum+matrix[r][nBands]);
}
dst.setPixel(dX, dY, dstPixel);
}
}
}
return dst;
}
/**
* Returns the bounding box of the transformed destination. Since
* this is not a geometric operation, the bounding box is the same for
* the source and destination.
* An <CODE>IllegalArgumentException</CODE> may be thrown if the number of
* bands in the source is incompatible with the matrix. See
* the class comments for more details.
*
* @param src The <CODE>Raster</CODE> to be filtered.
*
* @return The <CODE>Rectangle2D</CODE> representing the destination
* image's bounding box.
*
* @throws IllegalArgumentException If the number of bands in the source
* is incompatible with the matrix.
*/
public final Rectangle2D getBounds2D (Raster src) {
return src.getBounds();
}
/**
* Creates a zeroed destination <CODE>Raster</CODE> with the correct size
* and number of bands.
* An <CODE>IllegalArgumentException</CODE> may be thrown if the number of
* bands in the source is incompatible with the matrix. See
* the class comments for more details.
*
* @param src The <CODE>Raster</CODE> to be filtered.
*
* @return The zeroed destination <CODE>Raster</CODE>.
*/
public WritableRaster createCompatibleDestRaster (Raster src) {
int nBands = src.getNumBands();
if ((ncols != nBands) && (ncols != (nBands+1))) {
throw new IllegalArgumentException("Number of columns in the "+
"matrix ("+ncols+
") must be equal to the number"+
" of bands ([+1]) in src ("+
nBands+").");
}
if (src.getNumBands() == nrows) {
return src.createCompatibleWritableRaster();
}
else {
throw new IllegalArgumentException("Don't know how to create a "+
" compatible Raster with "+
nrows+" bands.");
}
}
/**
* Returns the location of the corresponding destination point given a
* point in the source <CODE>Raster</CODE>. If <CODE>dstPt</CODE> is
* specified, it is used to hold the return value.
* Since this is not a geometric operation, the point returned
* is the same as the specified <CODE>srcPt</CODE>.
*
* @param srcPt The <code>Point2D</code> that represents the point in
* the source <code>Raster</code>
* @param dstPt The <CODE>Point2D</CODE> in which to store the result.
*
* @return The <CODE>Point2D</CODE> in the destination image that
* corresponds to the specified point in the source image.
*/
public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
if (dstPt == null) {
dstPt = new Point2D.Float();
}
dstPt.setLocation(srcPt.getX(), srcPt.getY());
return dstPt;
}
/**
* Returns the rendering hints for this operation.
*
* @return The <CODE>RenderingHints</CODE> object associated with this
* operation. Returns null if no hints have been set.
*/
public final RenderingHints getRenderingHints() {
return hints;
}
}

View File

@@ -0,0 +1,849 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
/**
* This class represents image data which is stored in a band interleaved
* fashion and for
* which each sample of a pixel occupies one data element of the DataBuffer.
* It subclasses ComponentSampleModel but provides a more efficient
* implementation for accessing band interleaved image data than is provided
* by ComponentSampleModel. This class should typically be used when working
* with images which store sample data for each band in a different bank of the
* DataBuffer. Accessor methods are provided so that image data can be
* manipulated directly. Pixel stride is the number of
* data array elements between two samples for the same band on the same
* scanline. The pixel stride for a BandedSampleModel is one.
* Scanline stride is the number of data array elements between
* a given sample and the corresponding sample in the same column of the next
* scanline. Band offsets denote the number
* of data array elements from the first data array element of the bank
* of the DataBuffer holding each band to the first sample of the band.
* The bands are numbered from 0 to N-1.
* Bank indices denote the correspondence between a bank of the data buffer
* and a band of image data. This class supports
* {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
* {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
* {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
* {@link DataBuffer#TYPE_INT TYPE_INT},
* {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and
* {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes
*/
public final class BandedSampleModel extends ComponentSampleModel
{
/**
* Constructs a BandedSampleModel with the specified parameters.
* The pixel stride will be one data element. The scanline stride
* will be the same as the width. Each band will be stored in
* a separate bank and all band offsets will be zero.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of image
* data described.
* @param numBands The number of bands for the image data.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public BandedSampleModel(int dataType, int w, int h, int numBands) {
super(dataType, w, h, 1, w,
BandedSampleModel.createIndicesArray(numBands),
BandedSampleModel.createOffsetArray(numBands));
}
/**
* Constructs a BandedSampleModel with the specified parameters.
* The number of bands will be inferred from the lengths of the
* bandOffsets bankIndices arrays, which must be equal. The pixel
* stride will be one data element.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param scanlineStride The line stride of the of the image data.
* @param bankIndices The bank index for each band.
* @param bandOffsets The band offset for each band.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public BandedSampleModel(int dataType,
int w, int h,
int scanlineStride,
int bankIndices[],
int bandOffsets[]) {
super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets);
}
/**
* Creates a new BandedSampleModel with the specified
* width and height. The new BandedSampleModel will have the same
* number of bands, storage data type, and bank indices
* as this BandedSampleModel. The band offsets will be compressed
* such that the offset between bands will be w*pixelStride and
* the minimum of all of the band offsets is zero.
* @param w the width of the resulting <code>BandedSampleModel</code>
* @param h the height of the resulting <code>BandedSampleModel</code>
* @return a new <code>BandedSampleModel</code> with the specified
* width and height.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> equals either
* <code>Integer.MAX_VALUE</code> or
* <code>Integer.MIN_VALUE</code>
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
int[] bandOffs;
if (numBanks == 1) {
bandOffs = orderBands(bandOffsets, w*h);
}
else {
bandOffs = new int[bandOffsets.length];
}
SampleModel sampleModel =
new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs);
return sampleModel;
}
/**
* Creates a new BandedSampleModel with a subset of the bands of this
* BandedSampleModel. The new BandedSampleModel can be
* used with any DataBuffer that the existing BandedSampleModel
* can be used with. The new BandedSampleModel/DataBuffer
* combination will represent an image with a subset of the bands
* of the original BandedSampleModel/DataBuffer combination.
* @throws RasterFormatException if the number of bands is greater than
* the number of banks in this sample model.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public SampleModel createSubsetSampleModel(int bands[]) {
if (bands.length > bankIndices.length)
throw new RasterFormatException("There are only " +
bankIndices.length +
" bands");
int newBankIndices[] = new int[bands.length];
int newBandOffsets[] = new int[bands.length];
for (int i=0; i<bands.length; i++) {
newBankIndices[i] = bankIndices[bands[i]];
newBandOffsets[i] = bandOffsets[bands[i]];
}
return new BandedSampleModel(this.dataType, width, height,
this.scanlineStride,
newBankIndices, newBandOffsets);
}
/**
* Creates a DataBuffer that corresponds to this BandedSampleModel,
* The DataBuffer's data type, number of banks, and size
* will be consistent with this BandedSampleModel.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported types.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = scanlineStride * height;
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size, numBanks);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size, numBanks);
break;
case DataBuffer.TYPE_SHORT:
dataBuffer = new DataBufferShort(size, numBanks);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size, numBanks);
break;
case DataBuffer.TYPE_FLOAT:
dataBuffer = new DataBufferFloat(size, numBanks);
break;
case DataBuffer.TYPE_DOUBLE:
dataBuffer = new DataBufferDouble(size, numBanks);
break;
default:
throw new IllegalArgumentException("dataType is not one " +
"of the supported types.");
}
return dataBuffer;
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a BandedSampleModel, this will be the same
* as the data type, and samples will be returned one per array
* element. Generally, obj
* should be passed in as null, so that the Object will be created
* automatically and will be of the right primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
* whose storage layout is described by
* BandedSampleModel <code>bsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* BandedSampleModel bsm1, bsm2;
* DataBufferInt db1, db2;
* bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
* db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* If obj is non-null, it should be a primitive array of type TransferType.
* Otherwise, a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is non-null and is not large enough to hold
* the pixel data.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param obj If non-null, a primitive array in which to return
* the pixel data.
* @param data The DataBuffer containing the image data.
* @return the data for the specified pixel.
* @see #setDataElements(int, int, Object, DataBuffer)
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int numDataElems = getNumDataElements();
int pixelOffset = y*scanlineStride + x;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null) {
bdata = new byte[numDataElems];
} else {
bdata = (byte[])obj;
}
for (int i=0; i<numDataElems; i++) {
bdata[i] = (byte)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
short[] sdata;
if (obj == null) {
sdata = new short[numDataElems];
} else {
sdata = (short[])obj;
}
for (int i=0; i<numDataElems; i++) {
sdata[i] = (short)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)sdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null) {
idata = new int[numDataElems];
} else {
idata = (int[])obj;
}
for (int i=0; i<numDataElems; i++) {
idata[i] = data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)idata;
break;
case DataBuffer.TYPE_FLOAT:
float[] fdata;
if (obj == null) {
fdata = new float[numDataElems];
} else {
fdata = (float[])obj;
}
for (int i=0; i<numDataElems; i++) {
fdata[i] = data.getElemFloat(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)fdata;
break;
case DataBuffer.TYPE_DOUBLE:
double[] ddata;
if (obj == null) {
ddata = new double[numDataElems];
} else {
ddata = (double[])obj;
}
for (int i=0; i<numDataElems; i++) {
ddata[i] = data.getElemDouble(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)ddata;
break;
}
return obj;
}
/**
* Returns all samples for the specified pixel in an int array.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data
* @return the samples for the specified pixel.
* @see #setPixel(int, int, int[], DataBuffer)
*/
public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int[] pixels;
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int [numBands];
}
int pixelOffset = y*scanlineStride + x;
for (int i=0; i<numBands; i++) {
pixels[i] = data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
return pixels;
}
/**
* Returns all samples for the specified rectangle of pixels in
* an int array, one sample per data array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data
* @return the samples for the pixels within the specified region.
* @see #setPixels(int, int, int, int, int[], DataBuffer)
*/
public int[] getPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
int x1 = x + w;
int y1 = y + h;
if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
{
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int[] pixels;
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int[w*h*numBands];
}
for (int k = 0; k < numBands; k++) {
int lineOffset = y*scanlineStride + x + bandOffsets[k];
int srcOffset = k;
int bank = bankIndices[k];
for (int i = 0; i < h; i++) {
int pixelOffset = lineOffset;
for (int j = 0; j < w; j++) {
pixels[srcOffset] = data.getElem(bank, pixelOffset++);
srcOffset += numBands;
}
lineOffset += scanlineStride;
}
}
return pixels;
}
/**
* Returns as int the sample in a specified band for the pixel
* located at (x,y).
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to return
* @param data The DataBuffer containing the image data
* @return the sample in the specified band for the specified pixel.
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int sample =
data.getElem(bankIndices[b],
y*scanlineStride + x + bandOffsets[b]);
return sample;
}
/**
* Returns the sample in a specified band
* for the pixel located at (x,y) as a float.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to return
* @param data The DataBuffer containing the image data
* @return a float value that represents the sample in the specified
* band for the specified pixel.
*/
public float getSampleFloat(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
float sample = data.getElemFloat(bankIndices[b],
y*scanlineStride + x + bandOffsets[b]);
return sample;
}
/**
* Returns the sample in a specified band
* for a pixel located at (x,y) as a double.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to return
* @param data The DataBuffer containing the image data
* @return a double value that represents the sample in the specified
* band for the specified pixel.
*/
public double getSampleDouble(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
double sample = data.getElemDouble(bankIndices[b],
y*scanlineStride + x + bandOffsets[b]);
return sample;
}
/**
* Returns the samples in a specified band for the specified rectangle
* of pixels in an int array, one sample per data array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param b The band to return
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data
* @return the samples in the specified band for the pixels within
* the specified region.
* @see #setSamples(int, int, int, int, int, int[], DataBuffer)
*/
public int[] getSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int samples[];
if (iArray != null) {
samples = iArray;
} else {
samples = new int [w*h];
}
int lineOffset = y*scanlineStride + x + bandOffsets[b];
int srcOffset = 0;
int bank = bankIndices[b];
for (int i = 0; i < h; i++) {
int sampleOffset = lineOffset;
for (int j = 0; j < w; j++) {
samples[srcOffset++] = data.getElem(bank, sampleOffset++);
}
lineOffset += scanlineStride;
}
return samples;
}
/**
* Sets the data for a single pixel in the specified DataBuffer from a
* primitive array of type TransferType. For a BandedSampleModel,
* this will be the same as the data type, and samples are transferred
* one per array element.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
* whose storage layout is described by
* BandedSampleModel <code>bsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* BandedSampleModel bsm1, bsm2;
* DataBufferInt db1, db2;
* bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
* db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* obj must be a primitive array of type TransferType. Otherwise,
* a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is not large enough to hold the pixel data.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param obj If non-null, returns the primitive array in this
* object
* @param data The DataBuffer containing the image data
* @see #getDataElements(int, int, Object, DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int numDataElems = getNumDataElements();
int pixelOffset = y*scanlineStride + x;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
barray[i] & 0xff);
}
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
short[] sarray = (short[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
sarray[i] & 0xffff);
}
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
iarray[i]);
}
break;
case DataBuffer.TYPE_FLOAT:
float[] farray = (float[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElemFloat(bankIndices[i], pixelOffset + bandOffsets[i],
farray[i]);
}
break;
case DataBuffer.TYPE_DOUBLE:
double[] darray = (double[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElemDouble(bankIndices[i], pixelOffset + bandOffsets[i],
darray[i]);
}
break;
}
}
/**
* Sets a pixel in the DataBuffer using an int array of samples for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param iArray The input samples in an int array
* @param data The DataBuffer containing the image data
* @see #getPixel(int, int, int[], DataBuffer)
*/
public void setPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixelOffset = y*scanlineStride + x;
for (int i=0; i<numBands; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
iArray[i]);
}
}
/**
* Sets all samples for a rectangle of pixels from an int array containing
* one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param iArray The input samples in an int array
* @param data The DataBuffer containing the image data
* @see #getPixels(int, int, int, int, int[], DataBuffer)
*/
public void setPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
int x1 = x + w;
int y1 = y + h;
if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
{
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
for (int k = 0; k < numBands; k++) {
int lineOffset = y*scanlineStride + x + bandOffsets[k];
int srcOffset = k;
int bank = bankIndices[k];
for (int i = 0; i < h; i++) {
int pixelOffset = lineOffset;
for (int j = 0; j < w; j++) {
data.setElem(bank, pixelOffset++, iArray[srcOffset]);
srcOffset += numBands;
}
lineOffset += scanlineStride;
}
}
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using an int for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to set
* @param s The input sample as an int
* @param data The DataBuffer containing the image data
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b, int s,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
data.setElem(bankIndices[b],
y*scanlineStride + x + bandOffsets[b], s);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a float for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to set
* @param s The input sample as a float
* @param data The DataBuffer containing the image data
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b,
float s ,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
data.setElemFloat(bankIndices[b],
y*scanlineStride + x + bandOffsets[b], s);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a double for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to set
* @param s The input sample as a double
* @param data The DataBuffer containing the image data
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b,
double s,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
data.setElemDouble(bankIndices[b],
y*scanlineStride + x + bandOffsets[b], s);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from an int array containing one sample per data array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param b The band to set
* @param iArray The input sample array
* @param data The DataBuffer containing the image data
* @see #getSamples(int, int, int, int, int, int[], DataBuffer)
*/
public void setSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y*scanlineStride + x + bandOffsets[b];
int srcOffset = 0;
int bank = bankIndices[b];
for (int i = 0; i < h; i++) {
int sampleOffset = lineOffset;
for (int j = 0; j < w; j++) {
data.setElem(bank, sampleOffset++, iArray[srcOffset++]);
}
lineOffset += scanlineStride;
}
}
private static int[] createOffsetArray(int numBands) {
int[] bandOffsets = new int[numBands];
for (int i=0; i < numBands; i++) {
bandOffsets[i] = 0;
}
return bandOffsets;
}
private static int[] createIndicesArray(int numBands) {
int[] bankIndices = new int[numBands];
for (int i=0; i < numBands; i++) {
bankIndices[i] = i;
}
return bankIndices;
}
// Differentiate hash code from other ComponentSampleModel subclasses
public int hashCode() {
return super.hashCode() ^ 0x2;
}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.BufferCapabilities;
import java.awt.Graphics;
import java.awt.Image;
/**
* The <code>BufferStrategy</code> class represents the mechanism with which
* to organize complex memory on a particular <code>Canvas</code> or
* <code>Window</code>. Hardware and software limitations determine whether and
* how a particular buffer strategy can be implemented. These limitations
* are detectable through the capabilities of the
* <code>GraphicsConfiguration</code> used when creating the
* <code>Canvas</code> or <code>Window</code>.
* <p>
* It is worth noting that the terms <i>buffer</i> and <i>surface</i> are meant
* to be synonymous: an area of contiguous memory, either in video device
* memory or in system memory.
* <p>
* There are several types of complex buffer strategies, including
* sequential ring buffering and blit buffering.
* Sequential ring buffering (i.e., double or triple
* buffering) is the most common; an application draws to a single <i>back
* buffer</i> and then moves the contents to the front (display) in a single
* step, either by copying the data or moving the video pointer.
* Moving the video pointer exchanges the buffers so that the first buffer
* drawn becomes the <i>front buffer</i>, or what is currently displayed on the
* device; this is called <i>page flipping</i>.
* <p>
* Alternatively, the contents of the back buffer can be copied, or
* <i>blitted</i> forward in a chain instead of moving the video pointer.
* <pre>{@code
* Double buffering:
*
* *********** ***********
* * * ------> * *
* [To display] <---- * Front B * Show * Back B. * <---- Rendering
* * * <------ * *
* *********** ***********
*
* Triple buffering:
*
* [To *********** *********** ***********
* display] * * --------+---------+------> * *
* <---- * Front B * Show * Mid. B. * * Back B. * <---- Rendering
* * * <------ * * <----- * *
* *********** *********** ***********
*
* }</pre>
* <p>
* Here is an example of how buffer strategies can be created and used:
* <pre><code>
*
* // Check the capabilities of the GraphicsConfiguration
* ...
*
* // Create our component
* Window w = new Window(gc);
*
* // Show our window
* w.setVisible(true);
*
* // Create a general double-buffering strategy
* w.createBufferStrategy(2);
* BufferStrategy strategy = w.getBufferStrategy();
*
* // Main loop
* while (!done) {
* // Prepare for rendering the next frame
* // ...
*
* // Render single frame
* do {
* // The following loop ensures that the contents of the drawing buffer
* // are consistent in case the underlying surface was recreated
* do {
* // Get a new graphics context every time through the loop
* // to make sure the strategy is validated
* Graphics graphics = strategy.getDrawGraphics();
*
* // Render to graphics
* // ...
*
* // Dispose the graphics
* graphics.dispose();
*
* // Repeat the rendering if the drawing buffer contents
* // were restored
* } while (strategy.contentsRestored());
*
* // Display the buffer
* strategy.show();
*
* // Repeat the rendering if the drawing buffer was lost
* } while (strategy.contentsLost());
* }
*
* // Dispose the window
* w.setVisible(false);
* w.dispose();
* </code></pre>
*
* @see java.awt.Window
* @see java.awt.Canvas
* @see java.awt.GraphicsConfiguration
* @see VolatileImage
* @author Michael Martak
* @since 1.4
*/
public abstract class BufferStrategy {
/**
* Returns the <code>BufferCapabilities</code> for this
* <code>BufferStrategy</code>.
*
* @return the buffering capabilities of this strategy
*/
public abstract BufferCapabilities getCapabilities();
/**
* Creates a graphics context for the drawing buffer. This method may not
* be synchronized for performance reasons; use of this method by multiple
* threads should be handled at the application level. Disposal of the
* graphics object obtained must be handled by the application.
*
* @return a graphics context for the drawing buffer
*/
public abstract Graphics getDrawGraphics();
/**
* Returns whether the drawing buffer was lost since the last call to
* <code>getDrawGraphics</code>. Since the buffers in a buffer strategy
* are usually type <code>VolatileImage</code>, they may become lost.
* For a discussion on lost buffers, see <code>VolatileImage</code>.
*
* @return Whether or not the drawing buffer was lost since the last call
* to <code>getDrawGraphics</code>.
* @see java.awt.image.VolatileImage
*/
public abstract boolean contentsLost();
/**
* Returns whether the drawing buffer was recently restored from a lost
* state and reinitialized to the default background color (white).
* Since the buffers in a buffer strategy are usually type
* <code>VolatileImage</code>, they may become lost. If a surface has
* been recently restored from a lost state since the last call to
* <code>getDrawGraphics</code>, it may require repainting.
* For a discussion on lost buffers, see <code>VolatileImage</code>.
*
* @return Whether or not the drawing buffer was restored since the last
* call to <code>getDrawGraphics</code>.
* @see java.awt.image.VolatileImage
*/
public abstract boolean contentsRestored();
/**
* Makes the next available buffer visible by either copying the memory
* (blitting) or changing the display pointer (flipping).
*/
public abstract void show();
/**
* Releases system resources currently consumed by this
* <code>BufferStrategy</code> and
* removes it from the associated Component. After invoking this
* method, <code>getBufferStrategy</code> will return null. Trying
* to use a <code>BufferStrategy</code> after it has been disposed will
* result in undefined behavior.
*
* @see java.awt.Window#createBufferStrategy
* @see java.awt.Canvas#createBufferStrategy
* @see java.awt.Window#getBufferStrategy
* @see java.awt.Canvas#getBufferStrategy
* @since 1.6
*/
public void dispose() {
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,417 @@
/*
* Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.util.Hashtable;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageFilter;
/**
* The <code>BufferedImageFilter</code> class subclasses an
* <code>ImageFilter</code> to provide a simple means of
* using a single-source/single-destination image operator
* ({@link BufferedImageOp}) to filter a <code>BufferedImage</code>
* in the Image Producer/Consumer/Observer
* paradigm. Examples of these image operators are: {@link ConvolveOp},
* {@link AffineTransformOp} and {@link LookupOp}.
*
* @see ImageFilter
* @see BufferedImage
* @see BufferedImageOp
*/
public class BufferedImageFilter extends ImageFilter implements Cloneable {
BufferedImageOp bufferedImageOp;
ColorModel model;
int width;
int height;
byte[] bytePixels;
int[] intPixels;
/**
* Constructs a <code>BufferedImageFilter</code> with the
* specified single-source/single-destination operator.
* @param op the specified <code>BufferedImageOp</code> to
* use to filter a <code>BufferedImage</code>
* @throws NullPointerException if op is null
*/
public BufferedImageFilter (BufferedImageOp op) {
super();
if (op == null) {
throw new NullPointerException("Operation cannot be null");
}
bufferedImageOp = op;
}
/**
* Returns the <code>BufferedImageOp</code>.
* @return the operator of this <code>BufferedImageFilter</code>.
*/
public BufferedImageOp getBufferedImageOp() {
return bufferedImageOp;
}
/**
* Filters the information provided in the
* {@link ImageConsumer#setDimensions(int, int) setDimensions } method
* of the {@link ImageConsumer} interface.
* <p>
* Note: This method is intended to be called by the
* {@link ImageProducer} of the <code>Image</code> whose pixels are
* being filtered. Developers using this class to retrieve pixels from
* an image should avoid calling this method directly since that
* operation could result in problems with retrieving the requested
* pixels.
* <p>
* @param width the width to which to set the width of this
* <code>BufferedImageFilter</code>
* @param height the height to which to set the height of this
* <code>BufferedImageFilter</code>
* @see ImageConsumer#setDimensions
*/
public void setDimensions(int width, int height) {
if (width <= 0 || height <= 0) {
imageComplete(STATICIMAGEDONE);
return;
}
this.width = width;
this.height = height;
}
/**
* Filters the information provided in the
* {@link ImageConsumer#setColorModel(ColorModel) setColorModel} method
* of the <code>ImageConsumer</code> interface.
* <p>
* If <code>model</code> is <code>null</code>, this
* method clears the current <code>ColorModel</code> of this
* <code>BufferedImageFilter</code>.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code>
* whose pixels are being filtered. Developers using this
* class to retrieve pixels from an image
* should avoid calling this method directly since that
* operation could result in problems with retrieving the
* requested pixels.
* @param model the {@link ColorModel} to which to set the
* <code>ColorModel</code> of this <code>BufferedImageFilter</code>
* @see ImageConsumer#setColorModel
*/
public void setColorModel(ColorModel model) {
this.model = model;
}
private void convertToRGB() {
int size = width * height;
int newpixels[] = new int[size];
if (bytePixels != null) {
for (int i = 0; i < size; i++) {
newpixels[i] = this.model.getRGB(bytePixels[i] & 0xff);
}
} else if (intPixels != null) {
for (int i = 0; i < size; i++) {
newpixels[i] = this.model.getRGB(intPixels[i]);
}
}
bytePixels = null;
intPixels = newpixels;
this.model = ColorModel.getRGBdefault();
}
/**
* Filters the information provided in the <code>setPixels</code>
* method of the <code>ImageConsumer</code> interface which takes
* an array of bytes.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @throws IllegalArgumentException if width or height are less than
* zero.
* @see ImageConsumer#setPixels(int, int, int, int, ColorModel, byte[],
int, int)
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off,
int scansize) {
// Fix 4184230
if (w < 0 || h < 0) {
throw new IllegalArgumentException("Width ("+w+
") and height ("+h+
") must be > 0");
}
// Nothing to do
if (w == 0 || h == 0) {
return;
}
if (y < 0) {
int diff = -y;
if (diff >= h) {
return;
}
off += scansize * diff;
y += diff;
h -= diff;
}
if (y + h > height) {
h = height - y;
if (h <= 0) {
return;
}
}
if (x < 0) {
int diff = -x;
if (diff >= w) {
return;
}
off += diff;
x += diff;
w -= diff;
}
if (x + w > width) {
w = width - x;
if (w <= 0) {
return;
}
}
int dstPtr = y*width + x;
if (intPixels == null) {
if (bytePixels == null) {
bytePixels = new byte[width*height];
this.model = model;
} else if (this.model != model) {
convertToRGB();
}
if (bytePixels != null) {
for (int sh = h; sh > 0; sh--) {
System.arraycopy(pixels, off, bytePixels, dstPtr, w);
off += scansize;
dstPtr += width;
}
}
}
if (intPixels != null) {
int dstRem = width - w;
int srcRem = scansize - w;
for (int sh = h; sh > 0; sh--) {
for (int sw = w; sw > 0; sw--) {
intPixels[dstPtr++] = model.getRGB(pixels[off++]&0xff);
}
off += srcRem;
dstPtr += dstRem;
}
}
}
/**
* Filters the information provided in the <code>setPixels</code>
* method of the <code>ImageConsumer</code> interface which takes
* an array of integers.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose
* pixels are being filtered. Developers using this class to
* retrieve pixels from an image should avoid calling this method
* directly since that operation could result in problems
* with retrieving the requested pixels.
* @throws IllegalArgumentException if width or height are less than
* zero.
* @see ImageConsumer#setPixels(int, int, int, int, ColorModel, int[],
int, int)
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off,
int scansize) {
// Fix 4184230
if (w < 0 || h < 0) {
throw new IllegalArgumentException("Width ("+w+
") and height ("+h+
") must be > 0");
}
// Nothing to do
if (w == 0 || h == 0) {
return;
}
if (y < 0) {
int diff = -y;
if (diff >= h) {
return;
}
off += scansize * diff;
y += diff;
h -= diff;
}
if (y + h > height) {
h = height - y;
if (h <= 0) {
return;
}
}
if (x < 0) {
int diff = -x;
if (diff >= w) {
return;
}
off += diff;
x += diff;
w -= diff;
}
if (x + w > width) {
w = width - x;
if (w <= 0) {
return;
}
}
if (intPixels == null) {
if (bytePixels == null) {
intPixels = new int[width * height];
this.model = model;
} else {
convertToRGB();
}
}
int dstPtr = y*width + x;
if (this.model == model) {
for (int sh = h; sh > 0; sh--) {
System.arraycopy(pixels, off, intPixels, dstPtr, w);
off += scansize;
dstPtr += width;
}
} else {
if (this.model != ColorModel.getRGBdefault()) {
convertToRGB();
}
int dstRem = width - w;
int srcRem = scansize - w;
for (int sh = h; sh > 0; sh--) {
for (int sw = w; sw > 0; sw--) {
intPixels[dstPtr++] = model.getRGB(pixels[off++]);
}
off += srcRem;
dstPtr += dstRem;
}
}
}
/**
* Filters the information provided in the <code>imageComplete</code>
* method of the <code>ImageConsumer</code> interface.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param status the status of image loading
* @throws ImagingOpException if there was a problem calling the filter
* method of the <code>BufferedImageOp</code> associated with this
* instance.
* @see ImageConsumer#imageComplete
*/
public void imageComplete(int status) {
WritableRaster wr;
switch(status) {
case IMAGEERROR:
case IMAGEABORTED:
// reinitialize the params
model = null;
width = -1;
height = -1;
intPixels = null;
bytePixels = null;
break;
case SINGLEFRAMEDONE:
case STATICIMAGEDONE:
if (width <= 0 || height <= 0) break;
if (model instanceof DirectColorModel) {
if (intPixels == null) break;
wr = createDCMraster();
}
else if (model instanceof IndexColorModel) {
int[] bandOffsets = {0};
if (bytePixels == null) break;
DataBufferByte db = new DataBufferByte(bytePixels,
width*height);
wr = Raster.createInterleavedRaster(db, width, height, width,
1, bandOffsets, null);
}
else {
convertToRGB();
if (intPixels == null) break;
wr = createDCMraster();
}
BufferedImage bi = new BufferedImage(model, wr,
model.isAlphaPremultiplied(),
null);
bi = bufferedImageOp.filter(bi, null);
WritableRaster r = bi.getRaster();
ColorModel cm = bi.getColorModel();
int w = r.getWidth();
int h = r.getHeight();
consumer.setDimensions(w, h);
consumer.setColorModel(cm);
if (cm instanceof DirectColorModel) {
DataBufferInt db = (DataBufferInt) r.getDataBuffer();
consumer.setPixels(0, 0, w, h,
cm, db.getData(), 0, w);
}
else if (cm instanceof IndexColorModel) {
DataBufferByte db = (DataBufferByte) r.getDataBuffer();
consumer.setPixels(0, 0, w, h,
cm, db.getData(), 0, w);
}
else {
throw new InternalError("Unknown color model "+cm);
}
break;
}
consumer.imageComplete(status);
}
private final WritableRaster createDCMraster() {
WritableRaster wr;
DirectColorModel dcm = (DirectColorModel) model;
boolean hasAlpha = model.hasAlpha();
int[] bandMasks = new int[3+(hasAlpha ? 1 : 0)];
bandMasks[0] = dcm.getRedMask();
bandMasks[1] = dcm.getGreenMask();
bandMasks[2] = dcm.getBlueMask();
if (hasAlpha) {
bandMasks[3] = dcm.getAlphaMask();
}
DataBufferInt db = new DataBufferInt(intPixels, width*height);
wr = Raster.createPackedRaster(db, width, height, width,
bandMasks, null);
return wr;
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Point2D;
import java.awt.RenderingHints;
/**
* This interface describes single-input/single-output
* operations performed on <CODE>BufferedImage</CODE> objects.
* It is implemented by <CODE>AffineTransformOp</CODE>,
* <CODE>ConvolveOp</CODE>, <CODE>ColorConvertOp</CODE>, <CODE>RescaleOp</CODE>,
* and <CODE>LookupOp</CODE>. These objects can be passed into
* a <CODE>BufferedImageFilter</CODE> to operate on a
* <CODE>BufferedImage</CODE> in the
* ImageProducer-ImageFilter-ImageConsumer paradigm.
* <p>
* Classes that implement this
* interface must specify whether or not they allow in-place filtering--
* filter operations where the source object is equal to the destination
* object.
* <p>
* This interface cannot be used to describe more sophisticated operations
* such as those that take multiple sources. Note that this restriction also
* means that the values of the destination pixels prior to the operation are
* not used as input to the filter operation.
* @see BufferedImage
* @see BufferedImageFilter
* @see AffineTransformOp
* @see BandCombineOp
* @see ColorConvertOp
* @see ConvolveOp
* @see LookupOp
* @see RescaleOp
*/
public interface BufferedImageOp {
/**
* Performs a single-input/single-output operation on a
* <CODE>BufferedImage</CODE>.
* If the color models for the two images do not match, a color
* conversion into the destination color model is performed.
* If the destination image is null,
* a <CODE>BufferedImage</CODE> with an appropriate <CODE>ColorModel</CODE>
* is created.
* <p>
* An <CODE>IllegalArgumentException</CODE> may be thrown if the source
* and/or destination image is incompatible with the types of images $
* allowed by the class implementing this filter.
*
* @param src The <CODE>BufferedImage</CODE> to be filtered
* @param dest The <CODE>BufferedImage</CODE> in which to store the results$
*
* @return The filtered <CODE>BufferedImage</CODE>.
*
* @throws IllegalArgumentException If the source and/or destination
* image is not compatible with the types of images allowed by the class
* implementing this filter.
*/
public BufferedImage filter(BufferedImage src, BufferedImage dest);
/**
* Returns the bounding box of the filtered destination image.
* An <CODE>IllegalArgumentException</CODE> may be thrown if the source
* image is incompatible with the types of images allowed
* by the class implementing this filter.
*
* @param src The <CODE>BufferedImage</CODE> to be filtered
*
* @return The <CODE>Rectangle2D</CODE> representing the destination
* image's bounding box.
*/
public Rectangle2D getBounds2D (BufferedImage src);
/**
* Creates a zeroed destination image with the correct size and number of
* bands.
* An <CODE>IllegalArgumentException</CODE> may be thrown if the source
* image is incompatible with the types of images allowed
* by the class implementing this filter.
*
* @param src The <CODE>BufferedImage</CODE> to be filtered
* @param destCM <CODE>ColorModel</CODE> of the destination. If null,
* the <CODE>ColorModel</CODE> of the source is used.
*
* @return The zeroed destination image.
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM);
/**
* Returns the location of the corresponding destination point given a
* point in the source image. If <CODE>dstPt</CODE> is specified, it
* is used to hold the return value.
* @param srcPt the <code>Point2D</code> that represents the point in
* the source image
* @param dstPt The <CODE>Point2D</CODE> in which to store the result
*
* @return The <CODE>Point2D</CODE> in the destination image that
* corresponds to the specified point in the source image.
*/
public Point2D getPoint2D (Point2D srcPt, Point2D dstPt);
/**
* Returns the rendering hints for this operation.
*
* @return The <CODE>RenderingHints</CODE> object for this
* <CODE>BufferedImageOp</CODE>. Returns
* null if no hints have been set.
*/
public RenderingHints getRenderingHints();
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* This class defines a lookup table object. The output of a
* lookup operation using an object of this class is interpreted
* as an unsigned byte quantity. The lookup table contains byte
* data arrays for one or more bands (or components) of an image,
* and it contains an offset which will be subtracted from the
* input values before indexing the arrays. This allows an array
* smaller than the native data size to be provided for a
* constrained input. If there is only one array in the lookup
* table, it will be applied to all bands.
*
* @see ShortLookupTable
* @see LookupOp
*/
public class ByteLookupTable extends LookupTable {
/**
* Constants
*/
byte data[][];
/**
* Constructs a ByteLookupTable object from an array of byte
* arrays representing a lookup table for each
* band. The offset will be subtracted from input
* values before indexing into the arrays. The number of
* bands is the length of the data argument. The
* data array for each band is stored as a reference.
* @param offset the value subtracted from the input values
* before indexing into the arrays
* @param data an array of byte arrays representing a lookup
* table for each band
* @throws IllegalArgumentException if <code>offset</code> is
* is less than 0 or if the length of <code>data</code>
* is less than 1
*/
public ByteLookupTable(int offset, byte data[][]) {
super(offset,data.length);
numComponents = data.length;
numEntries = data[0].length;
this.data = new byte[numComponents][];
// Allocate the array and copy the data reference
for (int i=0; i < numComponents; i++) {
this.data[i] = data[i];
}
}
/**
* Constructs a ByteLookupTable object from an array
* of bytes representing a lookup table to be applied to all
* bands. The offset will be subtracted from input
* values before indexing into the array.
* The data array is stored as a reference.
* @param offset the value subtracted from the input values
* before indexing into the array
* @param data an array of bytes
* @throws IllegalArgumentException if <code>offset</code> is
* is less than 0 or if the length of <code>data</code>
* is less than 1
*/
public ByteLookupTable(int offset, byte data[]) {
super(offset,data.length);
numComponents = 1;
numEntries = data.length;
this.data = new byte[1][];
this.data[0] = data;
}
/**
* Returns the lookup table data by reference. If this ByteLookupTable
* was constructed using a single byte array, the length of the returned
* array is one.
* @return the data array of this <code>ByteLookupTable</code>.
*/
public final byte[][] getTable(){
return data;
}
/**
* Returns an array of samples of a pixel, translated with the lookup
* table. The source and destination array can be the same array.
* Array <code>dst</code> is returned.
*
* @param src the source array.
* @param dst the destination array. This array must be at least as
* long as <code>src</code>. If <code>dst</code> is
* <code>null</code>, a new array will be allocated having the
* same length as <code>src</code>.
* @return the array <code>dst</code>, an <code>int</code> array of
* samples.
* @exception ArrayIndexOutOfBoundsException if <code>src</code> is
* longer than <code>dst</code> or if for any element
* <code>i</code> of <code>src</code>,
* <code>src[i]-offset</code> is either less than zero or
* greater than or equal to the length of the lookup table
* for any band.
*/
public int[] lookupPixel(int[] src, int[] dst){
if (dst == null) {
// Need to alloc a new destination array
dst = new int[src.length];
}
if (numComponents == 1) {
// Apply one LUT to all bands
for (int i=0; i < src.length; i++) {
int s = src[i] - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = (int) data[0][s];
}
}
else {
for (int i=0; i < src.length; i++) {
int s = src[i] - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = (int) data[i][s];
}
}
return dst;
}
/**
* Returns an array of samples of a pixel, translated with the lookup
* table. The source and destination array can be the same array.
* Array <code>dst</code> is returned.
*
* @param src the source array.
* @param dst the destination array. This array must be at least as
* long as <code>src</code>. If <code>dst</code> is
* <code>null</code>, a new array will be allocated having the
* same length as <code>src</code>.
* @return the array <code>dst</code>, an <code>int</code> array of
* samples.
* @exception ArrayIndexOutOfBoundsException if <code>src</code> is
* longer than <code>dst</code> or if for any element
* <code>i</code> of <code>src</code>,
* {@code (src[i]&0xff)-offset} is either less than
* zero or greater than or equal to the length of the
* lookup table for any band.
*/
public byte[] lookupPixel(byte[] src, byte[] dst){
if (dst == null) {
// Need to alloc a new destination array
dst = new byte[src.length];
}
if (numComponents == 1) {
// Apply one LUT to all bands
for (int i=0; i < src.length; i++) {
int s = (src[i]&0xff) - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = data[0][s];
}
}
else {
for (int i=0; i < src.length; i++) {
int s = (src[i]&0xff) - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = data[i][s];
}
}
return dst;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,348 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.color.ICC_Profile;
import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.lang.annotation.Native;
import sun.awt.image.ImagingLib;
/**
* This class implements a convolution from the source
* to the destination.
* Convolution using a convolution kernel is a spatial operation that
* computes the output pixel from an input pixel by multiplying the kernel
* with the surround of the input pixel.
* This allows the output pixel to be affected by the immediate neighborhood
* in a way that can be mathematically specified with a kernel.
*<p>
* This class operates with BufferedImage data in which color components are
* premultiplied with the alpha component. If the Source BufferedImage has
* an alpha component, and the color components are not premultiplied with
* the alpha component, then the data are premultiplied before being
* convolved. If the Destination has color components which are not
* premultiplied, then alpha is divided out before storing into the
* Destination (if alpha is 0, the color components are set to 0). If the
* Destination has no alpha component, then the resulting alpha is discarded
* after first dividing it out of the color components.
* <p>
* Rasters are treated as having no alpha channel. If the above treatment
* of the alpha channel in BufferedImages is not desired, it may be avoided
* by getting the Raster of a source BufferedImage and using the filter method
* of this class which works with Rasters.
* <p>
* If a RenderingHints object is specified in the constructor, the
* color rendering hint and the dithering hint may be used when color
* conversion is required.
*<p>
* Note that the Source and the Destination may not be the same object.
* @see Kernel
* @see java.awt.RenderingHints#KEY_COLOR_RENDERING
* @see java.awt.RenderingHints#KEY_DITHERING
*/
public class ConvolveOp implements BufferedImageOp, RasterOp {
Kernel kernel;
int edgeHint;
RenderingHints hints;
/**
* Edge condition constants.
*/
/**
* Pixels at the edge of the destination image are set to zero. This
* is the default.
*/
@Native public static final int EDGE_ZERO_FILL = 0;
/**
* Pixels at the edge of the source image are copied to
* the corresponding pixels in the destination without modification.
*/
@Native public static final int EDGE_NO_OP = 1;
/**
* Constructs a ConvolveOp given a Kernel, an edge condition, and a
* RenderingHints object (which may be null).
* @param kernel the specified <code>Kernel</code>
* @param edgeCondition the specified edge condition
* @param hints the specified <code>RenderingHints</code> object
* @see Kernel
* @see #EDGE_NO_OP
* @see #EDGE_ZERO_FILL
* @see java.awt.RenderingHints
*/
public ConvolveOp(Kernel kernel, int edgeCondition, RenderingHints hints) {
this.kernel = kernel;
this.edgeHint = edgeCondition;
this.hints = hints;
}
/**
* Constructs a ConvolveOp given a Kernel. The edge condition
* will be EDGE_ZERO_FILL.
* @param kernel the specified <code>Kernel</code>
* @see Kernel
* @see #EDGE_ZERO_FILL
*/
public ConvolveOp(Kernel kernel) {
this.kernel = kernel;
this.edgeHint = EDGE_ZERO_FILL;
}
/**
* Returns the edge condition.
* @return the edge condition of this <code>ConvolveOp</code>.
* @see #EDGE_NO_OP
* @see #EDGE_ZERO_FILL
*/
public int getEdgeCondition() {
return edgeHint;
}
/**
* Returns the Kernel.
* @return the <code>Kernel</code> of this <code>ConvolveOp</code>.
*/
public final Kernel getKernel() {
return (Kernel) kernel.clone();
}
/**
* Performs a convolution on BufferedImages. Each component of the
* source image will be convolved (including the alpha component, if
* present).
* If the color model in the source image is not the same as that
* in the destination image, the pixels will be converted
* in the destination. If the destination image is null,
* a BufferedImage will be created with the source ColorModel.
* The IllegalArgumentException may be thrown if the source is the
* same as the destination.
* @param src the source <code>BufferedImage</code> to filter
* @param dst the destination <code>BufferedImage</code> for the
* filtered <code>src</code>
* @return the filtered <code>BufferedImage</code>
* @throws NullPointerException if <code>src</code> is <code>null</code>
* @throws IllegalArgumentException if <code>src</code> equals
* <code>dst</code>
* @throws ImagingOpException if <code>src</code> cannot be filtered
*/
public final BufferedImage filter (BufferedImage src, BufferedImage dst) {
if (src == null) {
throw new NullPointerException("src image is null");
}
if (src == dst) {
throw new IllegalArgumentException("src image cannot be the "+
"same as the dst image");
}
boolean needToConvert = false;
ColorModel srcCM = src.getColorModel();
ColorModel dstCM;
BufferedImage origDst = dst;
// Can't convolve an IndexColorModel. Need to expand it
if (srcCM instanceof IndexColorModel) {
IndexColorModel icm = (IndexColorModel) srcCM;
src = icm.convertToIntDiscrete(src.getRaster(), false);
srcCM = src.getColorModel();
}
if (dst == null) {
dst = createCompatibleDestImage(src, null);
dstCM = srcCM;
origDst = dst;
}
else {
dstCM = dst.getColorModel();
if (srcCM.getColorSpace().getType() !=
dstCM.getColorSpace().getType())
{
needToConvert = true;
dst = createCompatibleDestImage(src, null);
dstCM = dst.getColorModel();
}
else if (dstCM instanceof IndexColorModel) {
dst = createCompatibleDestImage(src, null);
dstCM = dst.getColorModel();
}
}
if (ImagingLib.filter(this, src, dst) == null) {
throw new ImagingOpException ("Unable to convolve src image");
}
if (needToConvert) {
ColorConvertOp ccop = new ColorConvertOp(hints);
ccop.filter(dst, origDst);
}
else if (origDst != dst) {
java.awt.Graphics2D g = origDst.createGraphics();
try {
g.drawImage(dst, 0, 0, null);
} finally {
g.dispose();
}
}
return origDst;
}
/**
* Performs a convolution on Rasters. Each band of the source Raster
* will be convolved.
* The source and destination must have the same number of bands.
* If the destination Raster is null, a new Raster will be created.
* The IllegalArgumentException may be thrown if the source is
* the same as the destination.
* @param src the source <code>Raster</code> to filter
* @param dst the destination <code>WritableRaster</code> for the
* filtered <code>src</code>
* @return the filtered <code>WritableRaster</code>
* @throws NullPointerException if <code>src</code> is <code>null</code>
* @throws ImagingOpException if <code>src</code> and <code>dst</code>
* do not have the same number of bands
* @throws ImagingOpException if <code>src</code> cannot be filtered
* @throws IllegalArgumentException if <code>src</code> equals
* <code>dst</code>
*/
public final WritableRaster filter (Raster src, WritableRaster dst) {
if (dst == null) {
dst = createCompatibleDestRaster(src);
}
else if (src == dst) {
throw new IllegalArgumentException("src image cannot be the "+
"same as the dst image");
}
else if (src.getNumBands() != dst.getNumBands()) {
throw new ImagingOpException("Different number of bands in src "+
" and dst Rasters");
}
if (ImagingLib.filter(this, src, dst) == null) {
throw new ImagingOpException ("Unable to convolve src image");
}
return dst;
}
/**
* Creates a zeroed destination image with the correct size and number
* of bands. If destCM is null, an appropriate ColorModel will be used.
* @param src Source image for the filter operation.
* @param destCM ColorModel of the destination. Can be null.
* @return a destination <code>BufferedImage</code> with the correct
* size and number of bands.
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel destCM) {
BufferedImage image;
int w = src.getWidth();
int h = src.getHeight();
WritableRaster wr = null;
if (destCM == null) {
destCM = src.getColorModel();
// Not much support for ICM
if (destCM instanceof IndexColorModel) {
destCM = ColorModel.getRGBdefault();
} else {
/* Create destination image as similar to the source
* as it possible...
*/
wr = src.getData().createCompatibleWritableRaster(w, h);
}
}
if (wr == null) {
/* This is the case when destination color model
* was explicitly specified (and it may be not compatible
* with source raster structure) or source is indexed image.
* We should use destination color model to create compatible
* destination raster here.
*/
wr = destCM.createCompatibleWritableRaster(w, h);
}
image = new BufferedImage (destCM, wr,
destCM.isAlphaPremultiplied(), null);
return image;
}
/**
* Creates a zeroed destination Raster with the correct size and number
* of bands, given this source.
*/
public WritableRaster createCompatibleDestRaster(Raster src) {
return src.createCompatibleWritableRaster();
}
/**
* Returns the bounding box of the filtered destination image. Since
* this is not a geometric operation, the bounding box does not
* change.
*/
public final Rectangle2D getBounds2D(BufferedImage src) {
return getBounds2D(src.getRaster());
}
/**
* Returns the bounding box of the filtered destination Raster. Since
* this is not a geometric operation, the bounding box does not
* change.
*/
public final Rectangle2D getBounds2D(Raster src) {
return src.getBounds();
}
/**
* Returns the location of the destination point given a
* point in the source. If dstPt is non-null, it will
* be used to hold the return value. Since this is not a geometric
* operation, the srcPt will equal the dstPt.
*/
public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
if (dstPt == null) {
dstPt = new Point2D.Float();
}
dstPt.setLocation(srcPt.getX(), srcPt.getY());
return dstPt;
}
/**
* Returns the rendering hints for this op.
*/
public final RenderingHints getRenderingHints() {
return hints;
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
import java.util.Hashtable;
import java.awt.Rectangle;
/**
* An ImageFilter class for cropping images.
* This class extends the basic ImageFilter Class to extract a given
* rectangular region of an existing Image and provide a source for a
* new image containing just the extracted region. It is meant to
* be used in conjunction with a FilteredImageSource object to produce
* cropped versions of existing images.
*
* @see FilteredImageSource
* @see ImageFilter
*
* @author Jim Graham
*/
public class CropImageFilter extends ImageFilter {
int cropX;
int cropY;
int cropW;
int cropH;
/**
* Constructs a CropImageFilter that extracts the absolute rectangular
* region of pixels from its source Image as specified by the x, y,
* w, and h parameters.
* @param x the x location of the top of the rectangle to be extracted
* @param y the y location of the top of the rectangle to be extracted
* @param w the width of the rectangle to be extracted
* @param h the height of the rectangle to be extracted
*/
public CropImageFilter(int x, int y, int w, int h) {
cropX = x;
cropY = y;
cropW = w;
cropH = h;
}
/**
* Passes along the properties from the source object after adding a
* property indicating the cropped region.
* This method invokes <code>super.setProperties</code>,
* which might result in additional properties being added.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*/
public void setProperties(Hashtable<?,?> props) {
Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
p.put("croprect", new Rectangle(cropX, cropY, cropW, cropH));
super.setProperties(p);
}
/**
* Override the source image's dimensions and pass the dimensions
* of the rectangular cropped region to the ImageConsumer.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose
* pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer
*/
public void setDimensions(int w, int h) {
consumer.setDimensions(cropW, cropH);
}
/**
* Determine whether the delivered byte pixels intersect the region to
* be extracted and passes through only that subset of pixels that
* appear in the output region.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose
* pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off,
int scansize) {
int x1 = x;
if (x1 < cropX) {
x1 = cropX;
}
int x2 = addWithoutOverflow(x, w);
if (x2 > cropX + cropW) {
x2 = cropX + cropW;
}
int y1 = y;
if (y1 < cropY) {
y1 = cropY;
}
int y2 = addWithoutOverflow(y, h);
if (y2 > cropY + cropH) {
y2 = cropY + cropH;
}
if (x1 >= x2 || y1 >= y2) {
return;
}
consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1),
model, pixels,
off + (y1 - y) * scansize + (x1 - x), scansize);
}
/**
* Determine if the delivered int pixels intersect the region to
* be extracted and pass through only that subset of pixels that
* appear in the output region.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose
* pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off,
int scansize) {
int x1 = x;
if (x1 < cropX) {
x1 = cropX;
}
int x2 = addWithoutOverflow(x, w);
if (x2 > cropX + cropW) {
x2 = cropX + cropW;
}
int y1 = y;
if (y1 < cropY) {
y1 = cropY;
}
int y2 = addWithoutOverflow(y, h);
if (y2 > cropY + cropH) {
y2 = cropY + cropH;
}
if (x1 >= x2 || y1 >= y2) {
return;
}
consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1),
model, pixels,
off + (y1 - y) * scansize + (x1 - x), scansize);
}
//check for potential overflow (see bug 4801285)
private int addWithoutOverflow(int x, int w) {
int x2 = x + w;
if ( x > 0 && w > 0 && x2 < 0 ) {
x2 = Integer.MAX_VALUE;
} else if( x < 0 && w < 0 && x2 > 0 ) {
x2 = Integer.MIN_VALUE;
}
return x2;
}
}

View File

@@ -0,0 +1,543 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import sun.java2d.StateTrackable.State;
import static sun.java2d.StateTrackable.State.*;
import sun.java2d.StateTrackableDelegate;
import sun.awt.image.SunWritableRaster;
import java.lang.annotation.Native;
/**
* This class exists to wrap one or more data arrays. Each data array in
* the DataBuffer is referred to as a bank. Accessor methods for getting
* and setting elements of the DataBuffer's banks exist with and without
* a bank specifier. The methods without a bank specifier use the default 0th
* bank. The DataBuffer can optionally take an offset per bank, so that
* data in an existing array can be used even if the interesting data
* doesn't start at array location zero. Getting or setting the 0th
* element of a bank, uses the (0+offset)th element of the array. The
* size field specifies how much of the data array is available for
* use. Size + offset for a given bank should never be greater
* than the length of the associated data array. The data type of
* a data buffer indicates the type of the data array(s) and may also
* indicate additional semantics, e.g. storing unsigned 8-bit data
* in elements of a byte array. The data type may be TYPE_UNDEFINED
* or one of the types defined below. Other types may be added in
* the future. Generally, an object of class DataBuffer will be cast down
* to one of its data type specific subclasses to access data type specific
* methods for improved performance. Currently, the Java 2D(tm) API
* image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT,
* TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data.
* @see java.awt.image.Raster
* @see java.awt.image.SampleModel
*/
public abstract class DataBuffer {
/** Tag for unsigned byte data. */
@Native public static final int TYPE_BYTE = 0;
/** Tag for unsigned short data. */
@Native public static final int TYPE_USHORT = 1;
/** Tag for signed short data. Placeholder for future use. */
@Native public static final int TYPE_SHORT = 2;
/** Tag for int data. */
@Native public static final int TYPE_INT = 3;
/** Tag for float data. Placeholder for future use. */
@Native public static final int TYPE_FLOAT = 4;
/** Tag for double data. Placeholder for future use. */
@Native public static final int TYPE_DOUBLE = 5;
/** Tag for undefined data. */
@Native public static final int TYPE_UNDEFINED = 32;
/** The data type of this DataBuffer. */
protected int dataType;
/** The number of banks in this DataBuffer. */
protected int banks;
/** Offset into default (first) bank from which to get the first element. */
protected int offset;
/** Usable size of all banks. */
protected int size;
/** Offsets into all banks. */
protected int offsets[];
/* The current StateTrackable state. */
StateTrackableDelegate theTrackable;
/** Size of the data types indexed by DataType tags defined above. */
private static final int dataTypeSize[] = {8,16,16,32,32,64};
/** Returns the size (in bits) of the data type, given a datatype tag.
* @param type the value of one of the defined datatype tags
* @return the size of the data type
* @throws IllegalArgumentException if <code>type</code> is less than
* zero or greater than {@link #TYPE_DOUBLE}
*/
public static int getDataTypeSize(int type) {
if (type < TYPE_BYTE || type > TYPE_DOUBLE) {
throw new IllegalArgumentException("Unknown data type "+type);
}
return dataTypeSize[type];
}
/**
* Constructs a DataBuffer containing one bank of the specified
* data type and size.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
*/
protected DataBuffer(int dataType, int size) {
this(UNTRACKABLE, dataType, size);
}
/**
* Constructs a DataBuffer containing one bank of the specified
* data type and size with the indicated initial {@link State State}.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size)
{
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = 1;
this.size = size;
this.offset = 0;
this.offsets = new int[1]; // init to 0 by new
}
/**
* Constructs a DataBuffer containing the specified number of
* banks. Each bank has the specified size and an offset of 0.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
*/
protected DataBuffer(int dataType, int size, int numBanks) {
this(UNTRACKABLE, dataType, size, numBanks);
}
/**
* Constructs a DataBuffer containing the specified number of
* banks with the indicated initial {@link State State}.
* Each bank has the specified size and an offset of 0.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size, int numBanks)
{
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = numBanks;
this.size = size;
this.offset = 0;
this.offsets = new int[banks]; // init to 0 by new
}
/**
* Constructs a DataBuffer that contains the specified number
* of banks. Each bank has the specified datatype, size and offset.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offset the offset for each bank
*/
protected DataBuffer(int dataType, int size, int numBanks, int offset) {
this(UNTRACKABLE, dataType, size, numBanks, offset);
}
/**
* Constructs a DataBuffer that contains the specified number
* of banks with the indicated initial {@link State State}.
* Each bank has the specified datatype, size and offset.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offset the offset for each bank
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size, int numBanks, int offset)
{
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = numBanks;
this.size = size;
this.offset = offset;
this.offsets = new int[numBanks];
for (int i = 0; i < numBanks; i++) {
this.offsets[i] = offset;
}
}
/**
* Constructs a DataBuffer which contains the specified number
* of banks. Each bank has the specified datatype and size. The
* offset for each bank is specified by its respective entry in
* the offsets array.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offsets an array containing an offset for each bank.
* @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
* does not equal the length of <code>offsets</code>
*/
protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) {
this(UNTRACKABLE, dataType, size, numBanks, offsets);
}
/**
* Constructs a DataBuffer which contains the specified number
* of banks with the indicated initial {@link State State}.
* Each bank has the specified datatype and size. The
* offset for each bank is specified by its respective entry in
* the offsets array.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offsets an array containing an offset for each bank.
* @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
* does not equal the length of <code>offsets</code>
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size, int numBanks, int offsets[])
{
if (numBanks != offsets.length) {
throw new ArrayIndexOutOfBoundsException("Number of banks" +
" does not match number of bank offsets");
}
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = numBanks;
this.size = size;
this.offset = offsets[0];
this.offsets = (int[])offsets.clone();
}
/** Returns the data type of this DataBuffer.
* @return the data type of this <code>DataBuffer</code>.
*/
public int getDataType() {
return dataType;
}
/** Returns the size (in array elements) of all banks.
* @return the size of all banks.
*/
public int getSize() {
return size;
}
/** Returns the offset of the default bank in array elements.
* @return the offset of the default bank.
*/
public int getOffset() {
return offset;
}
/** Returns the offsets (in array elements) of all the banks.
* @return the offsets of all banks.
*/
public int[] getOffsets() {
return (int[])offsets.clone();
}
/** Returns the number of banks in this DataBuffer.
* @return the number of banks.
*/
public int getNumBanks() {
return banks;
}
/**
* Returns the requested data array element from the first (default) bank
* as an integer.
* @param i the index of the requested data array element
* @return the data array element at the specified index.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return getElem(0,i);
}
/**
* Returns the requested data array element from the specified bank
* as an integer.
* @param bank the specified bank
* @param i the index of the requested data array element
* @return the data array element at the specified index from the
* specified bank at the specified index.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public abstract int getElem(int bank, int i);
/**
* Sets the requested data array element in the first (default) bank
* from the given integer.
* @param i the specified index into the data array
* @param val the data to set the element at the specified index in
* the data array
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
setElem(0,i,val);
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank the specified bank
* @param i the specified index into the data array
* @param val the data to set the element in the specified bank
* at the specified index in the data array
* @see #getElem(int)
* @see #getElem(int, int)
*/
public abstract void setElem(int bank, int i, int val);
/**
* Returns the requested data array element from the first (default) bank
* as a float. The implementation in this class is to cast getElem(i)
* to a float. Subclasses may override this method if another
* implementation is needed.
* @param i the index of the requested data array element
* @return a float value representing the data array element at the
* specified index.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int i) {
return (float)getElem(i);
}
/**
* Returns the requested data array element from the specified bank
* as a float. The implementation in this class is to cast
* {@link #getElem(int, int)}
* to a float. Subclasses can override this method if another
* implementation is needed.
* @param bank the specified bank
* @param i the index of the requested data array element
* @return a float value representing the data array element from the
* specified bank at the specified index.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int bank, int i) {
return (float)getElem(bank,i);
}
/**
* Sets the requested data array element in the first (default) bank
* from the given float. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses
* can override this method if another implementation is needed.
* @param i the specified index
* @param val the value to set the element at the specified index in
* the data array
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int i, float val) {
setElem(i,(int)val);
}
/**
* Sets the requested data array element in the specified bank
* from the given float. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses can
* override this method if another implementation is needed.
* @param bank the specified bank
* @param i the specified index
* @param val the value to set the element in the specified bank at
* the specified index in the data array
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int bank, int i, float val) {
setElem(bank,i,(int)val);
}
/**
* Returns the requested data array element from the first (default) bank
* as a double. The implementation in this class is to cast
* {@link #getElem(int)}
* to a double. Subclasses can override this method if another
* implementation is needed.
* @param i the specified index
* @return a double value representing the element at the specified
* index in the data array.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int i) {
return (double)getElem(i);
}
/**
* Returns the requested data array element from the specified bank as
* a double. The implementation in this class is to cast getElem(bank, i)
* to a double. Subclasses may override this method if another
* implementation is needed.
* @param bank the specified bank
* @param i the specified index
* @return a double value representing the element from the specified
* bank at the specified index in the data array.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int bank, int i) {
return (double)getElem(bank,i);
}
/**
* Sets the requested data array element in the first (default) bank
* from the given double. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses can
* override this method if another implementation is needed.
* @param i the specified index
* @param val the value to set the element at the specified index
* in the data array
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int i, double val) {
setElem(i,(int)val);
}
/**
* Sets the requested data array element in the specified bank
* from the given double. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses can
* override this method if another implementation is needed.
* @param bank the specified bank
* @param i the specified index
* @param val the value to set the element in the specified bank
* at the specified index of the data array
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int bank, int i, double val) {
setElem(bank,i,(int)val);
}
static int[] toIntArray(Object obj) {
if (obj instanceof int[]) {
return (int[])obj;
} else if (obj == null) {
return null;
} else if (obj instanceof short[]) {
short sdata[] = (short[])obj;
int idata[] = new int[sdata.length];
for (int i = 0; i < sdata.length; i++) {
idata[i] = (int)sdata[i] & 0xffff;
}
return idata;
} else if (obj instanceof byte[]) {
byte bdata[] = (byte[])obj;
int idata[] = new int[bdata.length];
for (int i = 0; i < bdata.length; i++) {
idata[i] = 0xff & (int)bdata[i];
}
return idata;
}
return null;
}
static {
SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() {
public byte[] getData(DataBufferByte dbb, int bank) {
return dbb.bankdata[bank];
}
public short[] getData(DataBufferUShort dbus, int bank) {
return dbus.bankdata[bank];
}
public int[] getData(DataBufferInt dbi, int bank) {
return dbi.bankdata[bank];
}
public StateTrackableDelegate getTrackable(DataBuffer db) {
return db.theTrackable;
}
public void setTrackable(DataBuffer db,
StateTrackableDelegate trackable)
{
db.theTrackable = trackable;
}
});
}
}

View File

@@ -0,0 +1,286 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally as bytes.
* Values stored in the byte array(s) of this <CODE>DataBuffer</CODE> are treated as
* unsigned values.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array, as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferByte extends DataBuffer
{
/** The default data bank. */
byte data[];
/** All data banks */
byte bankdata[][];
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank and the
* specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferByte(int size) {
super(STABLE, TYPE_BYTE, size);
data = new byte[size];
bankdata = new byte[1][];
bankdata[0] = data;
}
/**
* Constructs a byte based <CODE>DataBuffer</CODE> with the specified number of
* banks all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferByte(int size, int numBanks) {
super(STABLE, TYPE_BYTE, size, numBanks);
bankdata = new byte[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new byte[size];
}
data = bankdata[0];
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferByte(byte dataArray[], int size) {
super(UNTRACKABLE, TYPE_BYTE, size);
data = dataArray;
bankdata = new byte[1][];
bankdata[0] = data;
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array, size, and offset. <CODE>dataArray</CODE> must have at least
* <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
* through <CODE>offset</CODE> + <CODE>size</CODE> - 1
* should be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>. <CODE>dataArray</CODE>
* must have at least <CODE>offset</CODE> + <CODE>size</CODE> elements.
*/
public DataBufferByte(byte dataArray[], int size, int offset){
super(UNTRACKABLE, TYPE_BYTE, size, 1, offset);
data = dataArray;
bankdata = new byte[1][];
bankdata[0] = data;
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks is equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferByte(byte dataArray[][], int size) {
super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length);
bankdata = (byte[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays, size,
* and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding <CODE>offset</CODE>.
* There must be an entry in the <CODE>offset</CODE> array for each <CODE>dataArray</CODE>
* entry. For each bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be used by accessors of this
* <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferByte(byte dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length, offsets);
bankdata = (byte[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) byte data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first byte data array.
*/
public byte[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public byte[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public byte[][] getBankData() {
theTrackable.setUntrackable();
return (byte[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]) & 0xff;
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]) & 0xff;
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (byte)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (byte)val;
theTrackable.markDirty();
}
}

View File

@@ -0,0 +1,403 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <code>DataBuffer</code> and stores data internally
* in <code>double</code> form.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*
* @since 1.4
*/
public final class DataBufferDouble extends DataBuffer {
/** The array of data banks. */
double bankdata[][];
/** A reference to the default data bank. */
double data[];
/**
* Constructs a <code>double</code>-based <code>DataBuffer</code>
* with a specified size.
*
* @param size The number of elements in the <code>DataBuffer</code>.
*/
public DataBufferDouble(int size) {
super(STABLE, TYPE_DOUBLE, size);
data = new double[size];
bankdata = new double[1][];
bankdata[0] = data;
}
/**
* Constructs a <code>double</code>-based <code>DataBuffer</code>
* with a specified number of banks, all of which are of a
* specified size.
*
* @param size The number of elements in each bank of the
* <code>DataBuffer</code>.
* @param numBanks The number of banks in the <code>DataBuffer</code>.
*/
public DataBufferDouble(int size, int numBanks) {
super(STABLE, TYPE_DOUBLE, size, numBanks);
bankdata = new double[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new double[size];
}
data = bankdata[0];
}
/**
* Constructs a <code>double</code>-based <code>DataBuffer</code>
* with the specified data array. Only the first
* <code>size</code> elements are available for use by this
* <code>DataBuffer</code>. The array must be large enough to
* hold <code>size</code> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of <code>double</code>s to be used as the
* first and only bank of this <code>DataBuffer</code>.
* @param size The number of elements of the array to be used.
*/
public DataBufferDouble(double dataArray[], int size) {
super(UNTRACKABLE, TYPE_DOUBLE, size);
data = dataArray;
bankdata = new double[1][];
bankdata[0] = data;
}
/**
* Constructs a <code>double</code>-based <code>DataBuffer</code>
* with the specified data array. Only the elements between
* <code>offset</code> and <code>offset + size - 1</code> are
* available for use by this <code>DataBuffer</code>. The array
* must be large enough to hold <code>offset + size</code> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of <code>double</code>s to be used as the
* first and only bank of this <code>DataBuffer</code>.
* @param size The number of elements of the array to be used.
* @param offset The offset of the first element of the array
* that will be used.
*/
public DataBufferDouble(double dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_DOUBLE, size, 1, offset);
data = dataArray;
bankdata = new double[1][];
bankdata[0] = data;
}
/**
* Constructs a <code>double</code>-based <code>DataBuffer</code>
* with the specified data arrays. Only the first
* <code>size</code> elements of each array are available for use
* by this <code>DataBuffer</code>. The number of banks will be
* equal <code>to dataArray.length</code>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of arrays of <code>double</code>s to be
* used as the banks of this <code>DataBuffer</code>.
* @param size The number of elements of each array to be used.
*/
public DataBufferDouble(double dataArray[][], int size) {
super(UNTRACKABLE, TYPE_DOUBLE, size, dataArray.length);
bankdata = (double[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs a <code>double</code>-based <code>DataBuffer</code>
* with the specified data arrays, size, and per-bank offsets.
* The number of banks is equal to dataArray.length. Each array
* must be at least as large as <code>size</code> plus the
* corresponding offset. There must be an entry in the
* <code>offsets</code> array for each data array.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of arrays of <code>double</code>s to be
* used as the banks of this <code>DataBuffer</code>.
* @param size The number of elements of each array to be used.
* @param offsets An array of integer offsets, one for each bank.
*/
public DataBufferDouble(double dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_DOUBLE, size, dataArray.length, offsets);
bankdata = (double[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) <code>double</code> data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return the first double data array.
*/
public double[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank the data array
* @return the data array specified by <code>bank</code>.
*/
public double[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data array for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return all data arrays from this data buffer.
*/
public double[][] getBankData() {
theTrackable.setUntrackable();
return (double[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first
* (default) bank as an <code>int</code>.
*
* @param i The desired data array element.
* @return The data entry as an <code>int</code>.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]);
}
/**
* Returns the requested data array element from the specified
* bank as an <code>int</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
*
* @return The data entry as an <code>int</code>.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]);
}
/**
* Sets the requested data array element in the first (default)
* bank to the given <code>int</code>.
*
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (double)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* to the given <code>int</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (double)val;
theTrackable.markDirty();
}
/**
* Returns the requested data array element from the first
* (default) bank as a <code>float</code>.
*
* @param i The desired data array element.
*
* @return The data entry as a <code>float</code>.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int i) {
return (float)data[i+offset];
}
/**
* Returns the requested data array element from the specified
* bank as a <code>float</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
*
* @return The data entry as a <code>float</code>.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int bank, int i) {
return (float)bankdata[bank][i+offsets[bank]];
}
/**
* Sets the requested data array element in the first (default)
* bank to the given <code>float</code>.
*
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int i, float val) {
data[i+offset] = (double)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank to
* the given <code>float</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int bank, int i, float val) {
bankdata[bank][i+offsets[bank]] = (double)val;
theTrackable.markDirty();
}
/**
* Returns the requested data array element from the first
* (default) bank as a <code>double</code>.
*
* @param i The desired data array element.
*
* @return The data entry as a <code>double</code>.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int i) {
return data[i+offset];
}
/**
* Returns the requested data array element from the specified
* bank as a <code>double</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
*
* @return The data entry as a <code>double</code>.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int bank, int i) {
return bankdata[bank][i+offsets[bank]];
}
/**
* Sets the requested data array element in the first (default)
* bank to the given <code>double</code>.
*
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int i, double val) {
data[i+offset] = val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank to
* the given <code>double</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int bank, int i, double val) {
bankdata[bank][i+offsets[bank]] = val;
theTrackable.markDirty();
}
}

View File

@@ -0,0 +1,406 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <code>DataBuffer</code> and stores data internally
* in <code>float</code> form.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*
* @since 1.4
*/
public final class DataBufferFloat extends DataBuffer {
/** The array of data banks. */
float bankdata[][];
/** A reference to the default data bank. */
float data[];
/**
* Constructs a <code>float</code>-based <code>DataBuffer</code>
* with a specified size.
*
* @param size The number of elements in the DataBuffer.
*/
public DataBufferFloat(int size) {
super(STABLE, TYPE_FLOAT, size);
data = new float[size];
bankdata = new float[1][];
bankdata[0] = data;
}
/**
* Constructs a <code>float</code>-based <code>DataBuffer</code>
* with a specified number of banks, all of which are of a
* specified size.
*
* @param size The number of elements in each bank of the
* <code>DataBuffer</code>.
* @param numBanks The number of banks in the
* <code>DataBuffer</code>.
*/
public DataBufferFloat(int size, int numBanks) {
super(STABLE, TYPE_FLOAT, size, numBanks);
bankdata = new float[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new float[size];
}
data = bankdata[0];
}
/**
* Constructs a <code>float</code>-based <code>DataBuffer</code>
* with the specified data array. Only the first
* <code>size</code> elements are available for use by this
* <code>DataBuffer</code>. The array must be large enough to
* hold <code>size</code> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of <code>float</code>s to be used as the
* first and only bank of this <code>DataBuffer</code>.
* @param size The number of elements of the array to be used.
*/
public DataBufferFloat(float dataArray[], int size) {
super(UNTRACKABLE, TYPE_FLOAT, size);
data = dataArray;
bankdata = new float[1][];
bankdata[0] = data;
}
/**
* Constructs a <code>float</code>-based <code>DataBuffer</code>
* with the specified data array. Only the elements between
* <code>offset</code> and <code>offset + size - 1</code> are
* available for use by this <code>DataBuffer</code>. The array
* must be large enough to hold <code>offset + size</code>
* elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of <code>float</code>s to be used as the
* first and only bank of this <code>DataBuffer</code>.
* @param size The number of elements of the array to be used.
* @param offset The offset of the first element of the array
* that will be used.
*/
public DataBufferFloat(float dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_FLOAT, size, 1, offset);
data = dataArray;
bankdata = new float[1][];
bankdata[0] = data;
}
/**
* Constructs a <code>float</code>-based <code>DataBuffer</code>
* with the specified data arrays. Only the first
* <code>size</code> elements of each array are available for use
* by this <code>DataBuffer</code>. The number of banks will be
* equal to <code>dataArray.length</code>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of arrays of <code>float</code>s to be
* used as the banks of this <code>DataBuffer</code>.
* @param size The number of elements of each array to be used.
*/
public DataBufferFloat(float dataArray[][], int size) {
super(UNTRACKABLE, TYPE_FLOAT, size, dataArray.length);
bankdata = (float[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs a <code>float</code>-based <code>DataBuffer</code>
* with the specified data arrays, size, and per-bank offsets.
* The number of banks is equal to <code>dataArray.length</code>.
* Each array must be at least as large as <code>size</code> plus the
* corresponding offset. There must be an entry in the offsets
* array for each data array.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray An array of arrays of <code>float</code>s to be
* used as the banks of this <code>DataBuffer</code>.
* @param size The number of elements of each array to be used.
* @param offsets An array of integer offsets, one for each bank.
*/
public DataBufferFloat(float dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_FLOAT, size,dataArray.length, offsets);
bankdata = (float[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) <code>float</code> data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return the first float data array.
*/
public float[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank the data array
* @return the data array specified by <code>bank</code>.
*/
public float[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data array for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return all data arrays for this data buffer.
*/
public float[][] getBankData() {
theTrackable.setUntrackable();
return (float[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first
* (default) bank as an <code>int</code>.
*
* @param i The desired data array element.
*
* @return The data entry as an <code>int</code>.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]);
}
/**
* Returns the requested data array element from the specified
* bank as an <code>int</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
*
* @return The data entry as an <code>int</code>.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]);
}
/**
* Sets the requested data array element in the first (default)
* bank to the given <code>int</code>.
*
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (float)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank to
* the given <code>int</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (float)val;
theTrackable.markDirty();
}
/**
* Returns the requested data array element from the first
* (default) bank as a <code>float</code>.
*
* @param i The desired data array element.
*
* @return The data entry as a <code>float</code>.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int i) {
return data[i+offset];
}
/**
* Returns the requested data array element from the specified
* bank as a <code>float</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
*
* @return The data entry as a <code>float</code>.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int bank, int i) {
return bankdata[bank][i+offsets[bank]];
}
/**
* Sets the requested data array element in the first (default)
* bank to the given <code>float</code>.
*
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int i, float val) {
data[i+offset] = val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank to
* the given <code>float</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int bank, int i, float val) {
bankdata[bank][i+offsets[bank]] = val;
theTrackable.markDirty();
}
/**
* Returns the requested data array element from the first
* (default) bank as a <code>double</code>.
*
* @param i The desired data array element.
*
* @return The data entry as a <code>double</code>.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int i) {
return (double)data[i+offset];
}
/**
* Returns the requested data array element from the specified
* bank as a <code>double</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
*
* @return The data entry as a <code>double</code>.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int bank, int i) {
return (double)bankdata[bank][i+offsets[bank]];
}
/**
* Sets the requested data array element in the first (default)
* bank to the given <code>double</code>.
*
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int i, double val) {
data[i+offset] = (float)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank to
* the given <code>double</code>.
*
* @param bank The bank number.
* @param i The desired data array element.
* @param val The value to be set.
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int bank, int i, double val) {
bankdata[bank][i+offsets[bank]] = (float)val;
theTrackable.markDirty();
}
}

View File

@@ -0,0 +1,284 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally
* as integers.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferInt extends DataBuffer
{
/** The default data bank. */
int data[];
/** All data banks */
int bankdata[][];
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank
* and the specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int size) {
super(STABLE, TYPE_INT, size);
data = new int[size];
bankdata = new int[1][];
bankdata[0] = data;
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with the specified number of
* banks, all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int size, int numBanks) {
super(STABLE, TYPE_INT, size, numBanks);
bankdata = new int[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new int[size];
}
data = bankdata[0];
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferInt(int dataArray[], int size) {
super(UNTRACKABLE, TYPE_INT, size);
data = dataArray;
bankdata = new int[1][];
bankdata[0] = data;
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array, size, and offset. <CODE>dataArray</CODE> must have at least
* <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
* through <CODE>offset</CODE> + <CODE>size</CODE> - 1
* should be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>.
*/
public DataBufferInt(int dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_INT, size, 1, offset);
data = dataArray;
bankdata = new int[1][];
bankdata[0] = data;
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks will be equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int dataArray[][], int size) {
super(UNTRACKABLE, TYPE_INT, size, dataArray.length);
bankdata = (int [][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays, size,
* and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding offset. There must
* be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
* bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
* used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferInt(int dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_INT, size, dataArray.length, offsets);
bankdata = (int [][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) int data array in <CODE>DataBuffer</CODE>.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first integer data array.
*/
public int[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public int[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public int[][] getBankData() {
theTrackable.setUntrackable();
return (int [][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return data[i+offset];
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return bankdata[bank][i+offsets[bank]];
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* to the integer value <CODE>i</CODE>.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (int)val;
theTrackable.markDirty();
}
}

View File

@@ -0,0 +1,283 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally as shorts.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferShort extends DataBuffer
{
/** The default data bank. */
short data[];
/** All data banks */
short bankdata[][];
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with a single bank and the
* specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferShort(int size) {
super(STABLE, TYPE_SHORT,size);
data = new short[size];
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with the specified number of
* banks all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferShort(int size, int numBanks) {
super(STABLE, TYPE_SHORT,size,numBanks);
bankdata = new short[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new short[size];
}
data = bankdata[0];
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferShort(short dataArray[], int size) {
super(UNTRACKABLE, TYPE_SHORT, size);
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array, size, and offset. <CODE>dataArray</CODE> must have at least
* <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
* through <CODE>offset</CODE> + <CODE>size</CODE> - 1
* should be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>.
*/
public DataBufferShort(short dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_SHORT, size, 1, offset);
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks will be equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferShort(short dataArray[][], int size) {
super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length);
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays, size,
* and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding offset. There must
* be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
* bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
* used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferShort(short dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length, offsets);
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) byte data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first short data array.
*/
public short[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public short[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public short[][] getBankData() {
theTrackable.setUntrackable();
return (short[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]);
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]);
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (short)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (short)val;
theTrackable.markDirty();
}
}

View File

@@ -0,0 +1,318 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally as
* shorts. Values stored in the short array(s) of this <CODE>DataBuffer</CODE>
* are treated as unsigned values.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferUShort extends DataBuffer
{
/** The default data bank. */
short data[];
/** All data banks */
short bankdata[][];
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank and the
* specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferUShort(int size) {
super(STABLE, TYPE_USHORT, size);
data = new short[size];
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified number of
* banks, all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferUShort(int size, int numBanks) {
super(STABLE, TYPE_USHORT, size, numBanks);
bankdata = new short[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new short[size];
}
data = bankdata[0];
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
* using the specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferUShort(short dataArray[], int size) {
super(UNTRACKABLE, TYPE_USHORT, size);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
* using the specified array, size, and offset. <CODE>dataArray</CODE> must have at
* least <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements
* <CODE>offset</CODE> through <CODE>offset</CODE> + <CODE>size</CODE> - 1 should
* be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>.
*/
public DataBufferUShort(short dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_USHORT, size, 1, offset);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
if ((size+offset) > dataArray.length) {
throw new IllegalArgumentException("Length of dataArray is less "+
" than size+offset.");
}
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks will be equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferUShort(short dataArray[][], int size) {
super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
for (int i=0; i < dataArray.length; i++) {
if (dataArray[i] == null) {
throw new NullPointerException("dataArray["+i+"] is null");
}
}
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with specified arrays,
* size, and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding offset. There must
* be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
* bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
* used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferUShort(short dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length, offsets);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
for (int i=0; i < dataArray.length; i++) {
if (dataArray[i] == null) {
throw new NullPointerException("dataArray["+i+"] is null");
}
if ((size+offsets[i]) > dataArray[i].length) {
throw new IllegalArgumentException("Length of dataArray["+i+
"] is less than size+"+
"offsets["+i+"].");
}
}
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) unsigned-short data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first unsigned-short data array.
*/
public short[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public short[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public short[][] getBankData() {
theTrackable.setUntrackable();
return (short[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]&0xffff);
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]&0xffff);
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (short)(val&0xffff);
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (short)(val&0xffff);
theTrackable.markDirty();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,209 @@
/*
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.Image;
import java.awt.image.ImageFilter;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.util.Hashtable;
import java.awt.image.ColorModel;
/**
* This class is an implementation of the ImageProducer interface which
* takes an existing image and a filter object and uses them to produce
* image data for a new filtered version of the original image.
* Here is an example which filters an image by swapping the red and
* blue compents:
* <pre>
*
* Image src = getImage("doc:///demo/images/duke/T1.gif");
* ImageFilter colorfilter = new RedBlueSwapFilter();
* Image img = createImage(new FilteredImageSource(src.getSource(),
* colorfilter));
*
* </pre>
*
* @see ImageProducer
*
* @author Jim Graham
*/
public class FilteredImageSource implements ImageProducer {
ImageProducer src;
ImageFilter filter;
/**
* Constructs an ImageProducer object from an existing ImageProducer
* and a filter object.
* @param orig the specified <code>ImageProducer</code>
* @param imgf the specified <code>ImageFilter</code>
* @see ImageFilter
* @see java.awt.Component#createImage
*/
public FilteredImageSource(ImageProducer orig, ImageFilter imgf) {
src = orig;
filter = imgf;
}
private Hashtable proxies;
/**
* Adds the specified <code>ImageConsumer</code>
* to the list of consumers interested in data for the filtered image.
* An instance of the original <code>ImageFilter</code>
* is created
* (using the filter's <code>getFilterInstance</code> method)
* to manipulate the image data
* for the specified <code>ImageConsumer</code>.
* The newly created filter instance
* is then passed to the <code>addConsumer</code> method
* of the original <code>ImageProducer</code>.
*
* <p>
* This method is public as a side effect
* of this class implementing
* the <code>ImageProducer</code> interface.
* It should not be called from user code,
* and its behavior if called from user code is unspecified.
*
* @param ic the consumer for the filtered image
* @see ImageConsumer
*/
public synchronized void addConsumer(ImageConsumer ic) {
if (proxies == null) {
proxies = new Hashtable();
}
if (!proxies.containsKey(ic)) {
ImageFilter imgf = filter.getFilterInstance(ic);
proxies.put(ic, imgf);
src.addConsumer(imgf);
}
}
/**
* Determines whether an ImageConsumer is on the list of consumers
* currently interested in data for this image.
*
* <p>
* This method is public as a side effect
* of this class implementing
* the <code>ImageProducer</code> interface.
* It should not be called from user code,
* and its behavior if called from user code is unspecified.
*
* @param ic the specified <code>ImageConsumer</code>
* @return true if the ImageConsumer is on the list; false otherwise
* @see ImageConsumer
*/
public synchronized boolean isConsumer(ImageConsumer ic) {
return (proxies != null && proxies.containsKey(ic));
}
/**
* Removes an ImageConsumer from the list of consumers interested in
* data for this image.
*
* <p>
* This method is public as a side effect
* of this class implementing
* the <code>ImageProducer</code> interface.
* It should not be called from user code,
* and its behavior if called from user code is unspecified.
*
* @see ImageConsumer
*/
public synchronized void removeConsumer(ImageConsumer ic) {
if (proxies != null) {
ImageFilter imgf = (ImageFilter) proxies.get(ic);
if (imgf != null) {
src.removeConsumer(imgf);
proxies.remove(ic);
if (proxies.isEmpty()) {
proxies = null;
}
}
}
}
/**
* Starts production of the filtered image.
* If the specified <code>ImageConsumer</code>
* isn't already a consumer of the filtered image,
* an instance of the original <code>ImageFilter</code>
* is created
* (using the filter's <code>getFilterInstance</code> method)
* to manipulate the image data
* for the <code>ImageConsumer</code>.
* The filter instance for the <code>ImageConsumer</code>
* is then passed to the <code>startProduction</code> method
* of the original <code>ImageProducer</code>.
*
* <p>
* This method is public as a side effect
* of this class implementing
* the <code>ImageProducer</code> interface.
* It should not be called from user code,
* and its behavior if called from user code is unspecified.
*
* @param ic the consumer for the filtered image
* @see ImageConsumer
*/
public synchronized void startProduction(ImageConsumer ic) {
if (proxies == null) {
proxies = new Hashtable();
}
ImageFilter imgf = (ImageFilter) proxies.get(ic);
if (imgf == null) {
imgf = filter.getFilterInstance(ic);
proxies.put(ic, imgf);
}
src.startProduction(imgf);
}
/**
* Requests that a given ImageConsumer have the image data delivered
* one more time in top-down, left-right order. The request is
* handed to the ImageFilter for further processing, since the
* ability to preserve the pixel ordering depends on the filter.
*
* <p>
* This method is public as a side effect
* of this class implementing
* the <code>ImageProducer</code> interface.
* It should not be called from user code,
* and its behavior if called from user code is unspecified.
*
* @see ImageConsumer
*/
public synchronized void requestTopDownLeftRightResend(ImageConsumer ic) {
if (proxies != null) {
ImageFilter imgf = (ImageFilter) proxies.get(ic);
if (imgf != null) {
imgf.resendTopDownLeftRight(src);
}
}
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.util.Hashtable;
/**
* The interface for objects expressing interest in image data through
* the ImageProducer interfaces. When a consumer is added to an image
* producer, the producer delivers all of the data about the image
* using the method calls defined in this interface.
*
* @see ImageProducer
*
* @author Jim Graham
*/
public interface ImageConsumer {
/**
* The dimensions of the source image are reported using the
* setDimensions method call.
* @param width the width of the source image
* @param height the height of the source image
*/
void setDimensions(int width, int height);
/**
* Sets the extensible list of properties associated with this image.
* @param props the list of properties to be associated with this
* image
*/
void setProperties(Hashtable<?,?> props);
/**
* Sets the ColorModel object used for the majority of
* the pixels reported using the setPixels method
* calls. Note that each set of pixels delivered using setPixels
* contains its own ColorModel object, so no assumption should
* be made that this model will be the only one used in delivering
* pixel values. A notable case where multiple ColorModel objects
* may be seen is a filtered image when for each set of pixels
* that it filters, the filter
* determines whether the
* pixels can be sent on untouched, using the original ColorModel,
* or whether the pixels should be modified (filtered) and passed
* on using a ColorModel more convenient for the filtering process.
* @param model the specified <code>ColorModel</code>
* @see ColorModel
*/
void setColorModel(ColorModel model);
/**
* Sets the hints that the ImageConsumer uses to process the
* pixels delivered by the ImageProducer.
* The ImageProducer can deliver the pixels in any order, but
* the ImageConsumer may be able to scale or convert the pixels
* to the destination ColorModel more efficiently or with higher
* quality if it knows some information about how the pixels will
* be delivered up front. The setHints method should be called
* before any calls to any of the setPixels methods with a bit mask
* of hints about the manner in which the pixels will be delivered.
* If the ImageProducer does not follow the guidelines for the
* indicated hint, the results are undefined.
* @param hintflags a set of hints that the ImageConsumer uses to
* process the pixels
*/
void setHints(int hintflags);
/**
* The pixels will be delivered in a random order. This tells the
* ImageConsumer not to use any optimizations that depend on the
* order of pixel delivery, which should be the default assumption
* in the absence of any call to the setHints method.
* @see #setHints
*/
int RANDOMPIXELORDER = 1;
/**
* The pixels will be delivered in top-down, left-to-right order.
* @see #setHints
*/
int TOPDOWNLEFTRIGHT = 2;
/**
* The pixels will be delivered in (multiples of) complete scanlines
* at a time.
* @see #setHints
*/
int COMPLETESCANLINES = 4;
/**
* The pixels will be delivered in a single pass. Each pixel will
* appear in only one call to any of the setPixels methods. An
* example of an image format which does not meet this criterion
* is a progressive JPEG image which defines pixels in multiple
* passes, each more refined than the previous.
* @see #setHints
*/
int SINGLEPASS = 8;
/**
* The image contain a single static image. The pixels will be defined
* in calls to the setPixels methods and then the imageComplete method
* will be called with the STATICIMAGEDONE flag after which no more
* image data will be delivered. An example of an image type which
* would not meet these criteria would be the output of a video feed,
* or the representation of a 3D rendering being manipulated
* by the user. The end of each frame in those types of images will
* be indicated by calling imageComplete with the SINGLEFRAMEDONE flag.
* @see #setHints
* @see #imageComplete
*/
int SINGLEFRAME = 16;
/**
* Delivers the pixels of the image with one or more calls
* to this method. Each call specifies the location and
* size of the rectangle of source pixels that are contained in
* the array of pixels. The specified ColorModel object should
* be used to convert the pixels into their corresponding color
* and alpha components. Pixel (m,n) is stored in the pixels array
* at index (n * scansize + m + off). The pixels delivered using
* this method are all stored as bytes.
* @param x the X coordinate of the upper-left corner of the
* area of pixels to be set
* @param y the Y coordinate of the upper-left corner of the
* area of pixels to be set
* @param w the width of the area of pixels
* @param h the height of the area of pixels
* @param model the specified <code>ColorModel</code>
* @param pixels the array of pixels
* @param off the offset into the <code>pixels</code> array
* @param scansize the distance from one row of pixels to the next in
* the <code>pixels</code> array
* @see ColorModel
*/
void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off, int scansize);
/**
* The pixels of the image are delivered using one or more calls
* to the setPixels method. Each call specifies the location and
* size of the rectangle of source pixels that are contained in
* the array of pixels. The specified ColorModel object should
* be used to convert the pixels into their corresponding color
* and alpha components. Pixel (m,n) is stored in the pixels array
* at index (n * scansize + m + off). The pixels delivered using
* this method are all stored as ints.
* this method are all stored as ints.
* @param x the X coordinate of the upper-left corner of the
* area of pixels to be set
* @param y the Y coordinate of the upper-left corner of the
* area of pixels to be set
* @param w the width of the area of pixels
* @param h the height of the area of pixels
* @param model the specified <code>ColorModel</code>
* @param pixels the array of pixels
* @param off the offset into the <code>pixels</code> array
* @param scansize the distance from one row of pixels to the next in
* the <code>pixels</code> array
* @see ColorModel
*/
void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off, int scansize);
/**
* The imageComplete method is called when the ImageProducer is
* finished delivering all of the pixels that the source image
* contains, or when a single frame of a multi-frame animation has
* been completed, or when an error in loading or producing the
* image has occurred. The ImageConsumer should remove itself from the
* list of consumers registered with the ImageProducer at this time,
* unless it is interested in successive frames.
* @param status the status of image loading
* @see ImageProducer#removeConsumer
*/
void imageComplete(int status);
/**
* An error was encountered while producing the image.
* @see #imageComplete
*/
int IMAGEERROR = 1;
/**
* One frame of the image is complete but there are more frames
* to be delivered.
* @see #imageComplete
*/
int SINGLEFRAMEDONE = 2;
/**
* The image is complete and there are no more pixels or frames
* to be delivered.
* @see #imageComplete
*/
int STATICIMAGEDONE = 3;
/**
* The image creation process was deliberately aborted.
* @see #imageComplete
*/
int IMAGEABORTED = 4;
}

View File

@@ -0,0 +1,258 @@
/*
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.util.Hashtable;
/**
* This class implements a filter for the set of interface methods that
* are used to deliver data from an ImageProducer to an ImageConsumer.
* It is meant to be used in conjunction with a FilteredImageSource
* object to produce filtered versions of existing images. It is a
* base class that provides the calls needed to implement a "Null filter"
* which has no effect on the data being passed through. Filters should
* subclass this class and override the methods which deal with the
* data that needs to be filtered and modify it as necessary.
*
* @see FilteredImageSource
* @see ImageConsumer
*
* @author Jim Graham
*/
public class ImageFilter implements ImageConsumer, Cloneable {
/**
* The consumer of the particular image data stream for which this
* instance of the ImageFilter is filtering data. It is not
* initialized during the constructor, but rather during the
* getFilterInstance() method call when the FilteredImageSource
* is creating a unique instance of this object for a particular
* image data stream.
* @see #getFilterInstance
* @see ImageConsumer
*/
protected ImageConsumer consumer;
/**
* Returns a unique instance of an ImageFilter object which will
* actually perform the filtering for the specified ImageConsumer.
* The default implementation just clones this object.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @param ic the specified <code>ImageConsumer</code>
* @return an <code>ImageFilter</code> used to perform the
* filtering for the specified <code>ImageConsumer</code>.
*/
public ImageFilter getFilterInstance(ImageConsumer ic) {
ImageFilter instance = (ImageFilter) clone();
instance.consumer = ic;
return instance;
}
/**
* Filters the information provided in the setDimensions method
* of the ImageConsumer interface.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#setDimensions
*/
public void setDimensions(int width, int height) {
consumer.setDimensions(width, height);
}
/**
* Passes the properties from the source object along after adding a
* property indicating the stream of filters it has been run through.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*
* @param props the properties from the source object
* @exception NullPointerException if <code>props</code> is null
*/
public void setProperties(Hashtable<?,?> props) {
Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
Object o = p.get("filters");
if (o == null) {
p.put("filters", toString());
} else if (o instanceof String) {
p.put("filters", ((String) o)+toString());
}
consumer.setProperties(p);
}
/**
* Filter the information provided in the setColorModel method
* of the ImageConsumer interface.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#setColorModel
*/
public void setColorModel(ColorModel model) {
consumer.setColorModel(model);
}
/**
* Filters the information provided in the setHints method
* of the ImageConsumer interface.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#setHints
*/
public void setHints(int hints) {
consumer.setHints(hints);
}
/**
* Filters the information provided in the setPixels method of the
* ImageConsumer interface which takes an array of bytes.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#setPixels
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off,
int scansize) {
consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
}
/**
* Filters the information provided in the setPixels method of the
* ImageConsumer interface which takes an array of integers.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#setPixels
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off,
int scansize) {
consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
}
/**
* Filters the information provided in the imageComplete method of
* the ImageConsumer interface.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer#imageComplete
*/
public void imageComplete(int status) {
consumer.imageComplete(status);
}
/**
* Responds to a request for a TopDownLeftRight (TDLR) ordered resend
* of the pixel data from an <code>ImageConsumer</code>.
* When an <code>ImageConsumer</code> being fed
* by an instance of this <code>ImageFilter</code>
* requests a resend of the data in TDLR order,
* the <code>FilteredImageSource</code>
* invokes this method of the <code>ImageFilter</code>.
*
* <p>
*
* An <code>ImageFilter</code> subclass might override this method or not,
* depending on if and how it can send data in TDLR order.
* Three possibilities exist:
*
* <ul>
* <li>
* Do not override this method.
* This makes the subclass use the default implementation,
* which is to
* forward the request
* to the indicated <code>ImageProducer</code>
* using this filter as the requesting <code>ImageConsumer</code>.
* This behavior
* is appropriate if the filter can determine
* that it will forward the pixels
* in TDLR order if its upstream producer object
* sends them in TDLR order.
*
* <li>
* Override the method to simply send the data.
* This is appropriate if the filter can handle the request itself &#151;
* for example,
* if the generated pixels have been saved in some sort of buffer.
*
* <li>
* Override the method to do nothing.
* This is appropriate
* if the filter cannot produce filtered data in TDLR order.
* </ul>
*
* @see ImageProducer#requestTopDownLeftRightResend
* @param ip the ImageProducer that is feeding this instance of
* the filter - also the ImageProducer that the request should be
* forwarded to if necessary
* @exception NullPointerException if <code>ip</code> is null
*/
public void resendTopDownLeftRight(ImageProducer ip) {
ip.requestTopDownLeftRightResend(this);
}
/**
* Clones this object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.Image;
/**
* An asynchronous update interface for receiving notifications about
* Image information as the Image is constructed.
*
* @author Jim Graham
*/
public interface ImageObserver {
/**
* This method is called when information about an image which was
* previously requested using an asynchronous interface becomes
* available. Asynchronous interfaces are method calls such as
* getWidth(ImageObserver) and drawImage(img, x, y, ImageObserver)
* which take an ImageObserver object as an argument. Those methods
* register the caller as interested either in information about
* the overall image itself (in the case of getWidth(ImageObserver))
* or about an output version of an image (in the case of the
* drawImage(img, x, y, [w, h,] ImageObserver) call).
*
* <p>This method
* should return true if further updates are needed or false if the
* required information has been acquired. The image which was being
* tracked is passed in using the img argument. Various constants
* are combined to form the infoflags argument which indicates what
* information about the image is now available. The interpretation
* of the x, y, width, and height arguments depends on the contents
* of the infoflags argument.
* <p>
* The <code>infoflags</code> argument should be the bitwise inclusive
* <b>OR</b> of the following flags: <code>WIDTH</code>,
* <code>HEIGHT</code>, <code>PROPERTIES</code>, <code>SOMEBITS</code>,
* <code>FRAMEBITS</code>, <code>ALLBITS</code>, <code>ERROR</code>,
* <code>ABORT</code>.
*
* @param img the image being observed.
* @param infoflags the bitwise inclusive OR of the following
* flags: <code>WIDTH</code>, <code>HEIGHT</code>,
* <code>PROPERTIES</code>, <code>SOMEBITS</code>,
* <code>FRAMEBITS</code>, <code>ALLBITS</code>,
* <code>ERROR</code>, <code>ABORT</code>.
* @param x the <i>x</i> coordinate.
* @param y the <i>y</i> coordinate.
* @param width the width.
* @param height the height.
* @return <code>false</code> if the infoflags indicate that the
* image is completely loaded; <code>true</code> otherwise.
*
* @see #WIDTH
* @see #HEIGHT
* @see #PROPERTIES
* @see #SOMEBITS
* @see #FRAMEBITS
* @see #ALLBITS
* @see #ERROR
* @see #ABORT
* @see Image#getWidth
* @see Image#getHeight
* @see java.awt.Graphics#drawImage
*/
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int width, int height);
/**
* This flag in the infoflags argument to imageUpdate indicates that
* the width of the base image is now available and can be taken
* from the width argument to the imageUpdate callback method.
* @see Image#getWidth
* @see #imageUpdate
*/
public static final int WIDTH = 1;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* the height of the base image is now available and can be taken
* from the height argument to the imageUpdate callback method.
* @see Image#getHeight
* @see #imageUpdate
*/
public static final int HEIGHT = 2;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* the properties of the image are now available.
* @see Image#getProperty
* @see #imageUpdate
*/
public static final int PROPERTIES = 4;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* more pixels needed for drawing a scaled variation of the image
* are available. The bounding box of the new pixels can be taken
* from the x, y, width, and height arguments to the imageUpdate
* callback method.
* @see java.awt.Graphics#drawImage
* @see #imageUpdate
*/
public static final int SOMEBITS = 8;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* another complete frame of a multi-frame image which was previously
* drawn is now available to be drawn again. The x, y, width, and height
* arguments to the imageUpdate callback method should be ignored.
* @see java.awt.Graphics#drawImage
* @see #imageUpdate
*/
public static final int FRAMEBITS = 16;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* a static image which was previously drawn is now complete and can
* be drawn again in its final form. The x, y, width, and height
* arguments to the imageUpdate callback method should be ignored.
* @see java.awt.Graphics#drawImage
* @see #imageUpdate
*/
public static final int ALLBITS = 32;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* an image which was being tracked asynchronously has encountered
* an error. No further information will become available and
* drawing the image will fail.
* As a convenience, the ABORT flag will be indicated at the same
* time to indicate that the image production was aborted.
* @see #imageUpdate
*/
public static final int ERROR = 64;
/**
* This flag in the infoflags argument to imageUpdate indicates that
* an image which was being tracked asynchronously was aborted before
* production was complete. No more information will become available
* without further action to trigger another image production sequence.
* If the ERROR flag was not also set in this image update, then
* accessing any of the data in the image will restart the production
* again, probably from the beginning.
* @see #imageUpdate
*/
public static final int ABORT = 128;
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* The interface for objects which can produce the image data for Images.
* Each image contains an ImageProducer which is used to reconstruct
* the image whenever it is needed, for example, when a new size of the
* Image is scaled, or when the width or height of the Image is being
* requested.
*
* @see ImageConsumer
*
* @author Jim Graham
*/
public interface ImageProducer {
/**
* Registers an <code>ImageConsumer</code> with the
* <code>ImageProducer</code> for access to the image data
* during a later reconstruction of the <code>Image</code>.
* The <code>ImageProducer</code> may, at its discretion,
* start delivering the image data to the consumer
* using the <code>ImageConsumer</code> interface immediately,
* or when the next available image reconstruction is triggered
* by a call to the <code>startProduction</code> method.
* @param ic the specified <code>ImageConsumer</code>
* @see #startProduction
*/
public void addConsumer(ImageConsumer ic);
/**
* Determines if a specified <code>ImageConsumer</code>
* object is currently registered with this
* <code>ImageProducer</code> as one of its consumers.
* @param ic the specified <code>ImageConsumer</code>
* @return <code>true</code> if the specified
* <code>ImageConsumer</code> is registered with
* this <code>ImageProducer</code>;
* <code>false</code> otherwise.
*/
public boolean isConsumer(ImageConsumer ic);
/**
* Removes the specified <code>ImageConsumer</code> object
* from the list of consumers currently registered to
* receive image data. It is not considered an error
* to remove a consumer that is not currently registered.
* The <code>ImageProducer</code> should stop sending data
* to this consumer as soon as is feasible.
* @param ic the specified <code>ImageConsumer</code>
*/
public void removeConsumer(ImageConsumer ic);
/**
* Registers the specified <code>ImageConsumer</code> object
* as a consumer and starts an immediate reconstruction of
* the image data which will then be delivered to this
* consumer and any other consumer which might have already
* been registered with the producer. This method differs
* from the addConsumer method in that a reproduction of
* the image data should be triggered as soon as possible.
* @param ic the specified <code>ImageConsumer</code>
* @see #addConsumer
*/
public void startProduction(ImageConsumer ic);
/**
* Requests, on behalf of the <code>ImageConsumer</code>,
* that the <code>ImageProducer</code> attempt to resend
* the image data one more time in TOPDOWNLEFTRIGHT order
* so that higher quality conversion algorithms which
* depend on receiving pixels in order can be used to
* produce a better output version of the image. The
* <code>ImageProducer</code> is free to
* ignore this call if it cannot resend the data in that
* order. If the data can be resent, the
* <code>ImageProducer</code> should respond by executing
* the following minimum set of <code>ImageConsumer</code>
* method calls:
* <pre>{@code
* ic.setHints(TOPDOWNLEFTRIGHT | < otherhints >);
* ic.setPixels(...); // As many times as needed
* ic.imageComplete();
* }</pre>
* @param ic the specified <code>ImageConsumer</code>
* @see ImageConsumer#setHints
*/
public void requestTopDownLeftRightResend(ImageConsumer ic);
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* The <code>ImagingOpException</code> is thrown if one of the
* {@link BufferedImageOp} or {@link RasterOp} filter methods cannot
* process the image.
*/
public class ImagingOpException extends java.lang.RuntimeException {
/**
* Constructs an <code>ImagingOpException</code> object with the
* specified message.
* @param s the message to generate when a
* <code>ImagingOpException</code> is thrown
*/
public ImagingOpException(String s) {
super (s);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* The <code>Kernel</code> class defines a matrix that describes how a
* specified pixel and its surrounding pixels affect the value
* computed for the pixel's position in the output image of a filtering
* operation. The X origin and Y origin indicate the kernel matrix element
* that corresponds to the pixel position for which an output value is
* being computed.
*
* @see ConvolveOp
*/
public class Kernel implements Cloneable {
private int width;
private int height;
private int xOrigin;
private int yOrigin;
private float data[];
private static native void initIDs();
static {
ColorModel.loadLibraries();
initIDs();
}
/**
* Constructs a <code>Kernel</code> object from an array of floats.
* The first <code>width</code>*<code>height</code> elements of
* the <code>data</code> array are copied.
* If the length of the <code>data</code> array is less
* than width*height, an <code>IllegalArgumentException</code> is thrown.
* The X origin is (width-1)/2 and the Y origin is (height-1)/2.
* @param width width of the kernel
* @param height height of the kernel
* @param data kernel data in row major order
* @throws IllegalArgumentException if the length of <code>data</code>
* is less than the product of <code>width</code> and
* <code>height</code>
*/
public Kernel(int width, int height, float data[]) {
this.width = width;
this.height = height;
this.xOrigin = (width-1)>>1;
this.yOrigin = (height-1)>>1;
int len = width*height;
if (data.length < len) {
throw new IllegalArgumentException("Data array too small "+
"(is "+data.length+
" and should be "+len);
}
this.data = new float[len];
System.arraycopy(data, 0, this.data, 0, len);
}
/**
* Returns the X origin of this <code>Kernel</code>.
* @return the X origin.
*/
final public int getXOrigin(){
return xOrigin;
}
/**
* Returns the Y origin of this <code>Kernel</code>.
* @return the Y origin.
*/
final public int getYOrigin() {
return yOrigin;
}
/**
* Returns the width of this <code>Kernel</code>.
* @return the width of this <code>Kernel</code>.
*/
final public int getWidth() {
return width;
}
/**
* Returns the height of this <code>Kernel</code>.
* @return the height of this <code>Kernel</code>.
*/
final public int getHeight() {
return height;
}
/**
* Returns the kernel data in row major order.
* The <code>data</code> array is returned. If <code>data</code>
* is <code>null</code>, a new array is allocated.
* @param data if non-null, contains the returned kernel data
* @return the <code>data</code> array containing the kernel data
* in row major order or, if <code>data</code> is
* <code>null</code>, a newly allocated array containing
* the kernel data in row major order
* @throws IllegalArgumentException if <code>data</code> is less
* than the size of this <code>Kernel</code>
*/
final public float[] getKernelData(float[] data) {
if (data == null) {
data = new float[this.data.length];
}
else if (data.length < this.data.length) {
throw new IllegalArgumentException("Data array too small "+
"(should be "+this.data.length+
" but is "+
data.length+" )");
}
System.arraycopy(this.data, 0, data, 0, this.data.length);
return data;
}
/**
* Clones this object.
* @return a clone of this object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
}

View File

@@ -0,0 +1,567 @@
/*
* Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.color.ColorSpace;
import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import sun.awt.image.ImagingLib;
/**
* This class implements a lookup operation from the source
* to the destination. The LookupTable object may contain a single array
* or multiple arrays, subject to the restrictions below.
* <p>
* For Rasters, the lookup operates on bands. The number of
* lookup arrays may be one, in which case the same array is
* applied to all bands, or it must equal the number of Source
* Raster bands.
* <p>
* For BufferedImages, the lookup operates on color and alpha components.
* The number of lookup arrays may be one, in which case the
* same array is applied to all color (but not alpha) components.
* Otherwise, the number of lookup arrays may
* equal the number of Source color components, in which case no
* lookup of the alpha component (if present) is performed.
* If neither of these cases apply, the number of lookup arrays
* must equal the number of Source color components plus alpha components,
* in which case lookup is performed for all color and alpha components.
* This allows non-uniform rescaling of multi-band BufferedImages.
* <p>
* BufferedImage sources with premultiplied alpha data are treated in the same
* manner as non-premultiplied images for purposes of the lookup. That is,
* the lookup is done per band on the raw data of the BufferedImage source
* without regard to whether the data is premultiplied. If a color conversion
* is required to the destination ColorModel, the premultiplied state of
* both source and destination will be taken into account for this step.
* <p>
* Images with an IndexColorModel cannot be used.
* <p>
* If a RenderingHints object is specified in the constructor, the
* color rendering hint and the dithering hint may be used when color
* conversion is required.
* <p>
* This class allows the Source to be the same as the Destination.
*
* @see LookupTable
* @see java.awt.RenderingHints#KEY_COLOR_RENDERING
* @see java.awt.RenderingHints#KEY_DITHERING
*/
public class LookupOp implements BufferedImageOp, RasterOp {
private LookupTable ltable;
private int numComponents;
RenderingHints hints;
/**
* Constructs a <code>LookupOp</code> object given the lookup
* table and a <code>RenderingHints</code> object, which might
* be <code>null</code>.
* @param lookup the specified <code>LookupTable</code>
* @param hints the specified <code>RenderingHints</code>,
* or <code>null</code>
*/
public LookupOp(LookupTable lookup, RenderingHints hints) {
this.ltable = lookup;
this.hints = hints;
numComponents = ltable.getNumComponents();
}
/**
* Returns the <code>LookupTable</code>.
* @return the <code>LookupTable</code> of this
* <code>LookupOp</code>.
*/
public final LookupTable getTable() {
return ltable;
}
/**
* Performs a lookup operation on a <code>BufferedImage</code>.
* If the color model in the source image is not the same as that
* in the destination image, the pixels will be converted
* in the destination. If the destination image is <code>null</code>,
* a <code>BufferedImage</code> will be created with an appropriate
* <code>ColorModel</code>. An <code>IllegalArgumentException</code>
* might be thrown if the number of arrays in the
* <code>LookupTable</code> does not meet the restrictions
* stated in the class comment above, or if the source image
* has an <code>IndexColorModel</code>.
* @param src the <code>BufferedImage</code> to be filtered
* @param dst the <code>BufferedImage</code> in which to
* store the results of the filter operation
* @return the filtered <code>BufferedImage</code>.
* @throws IllegalArgumentException if the number of arrays in the
* <code>LookupTable</code> does not meet the restrictions
* described in the class comments, or if the source image
* has an <code>IndexColorModel</code>.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
ColorModel srcCM = src.getColorModel();
int numBands = srcCM.getNumColorComponents();
ColorModel dstCM;
if (srcCM instanceof IndexColorModel) {
throw new
IllegalArgumentException("LookupOp cannot be "+
"performed on an indexed image");
}
int numComponents = ltable.getNumComponents();
if (numComponents != 1 &&
numComponents != srcCM.getNumComponents() &&
numComponents != srcCM.getNumColorComponents())
{
throw new IllegalArgumentException("Number of arrays in the "+
" lookup table ("+
numComponents+
" is not compatible with the "+
" src image: "+src);
}
boolean needToConvert = false;
int width = src.getWidth();
int height = src.getHeight();
if (dst == null) {
dst = createCompatibleDestImage(src, null);
dstCM = srcCM;
}
else {
if (width != dst.getWidth()) {
throw new
IllegalArgumentException("Src width ("+width+
") not equal to dst width ("+
dst.getWidth()+")");
}
if (height != dst.getHeight()) {
throw new
IllegalArgumentException("Src height ("+height+
") not equal to dst height ("+
dst.getHeight()+")");
}
dstCM = dst.getColorModel();
if (srcCM.getColorSpace().getType() !=
dstCM.getColorSpace().getType())
{
needToConvert = true;
dst = createCompatibleDestImage(src, null);
}
}
BufferedImage origDst = dst;
if (ImagingLib.filter(this, src, dst) == null) {
// Do it the slow way
WritableRaster srcRaster = src.getRaster();
WritableRaster dstRaster = dst.getRaster();
if (srcCM.hasAlpha()) {
if (numBands-1 == numComponents || numComponents == 1) {
int minx = srcRaster.getMinX();
int miny = srcRaster.getMinY();
int[] bands = new int[numBands-1];
for (int i=0; i < numBands-1; i++) {
bands[i] = i;
}
srcRaster =
srcRaster.createWritableChild(minx, miny,
srcRaster.getWidth(),
srcRaster.getHeight(),
minx, miny,
bands);
}
}
if (dstCM.hasAlpha()) {
int dstNumBands = dstRaster.getNumBands();
if (dstNumBands-1 == numComponents || numComponents == 1) {
int minx = dstRaster.getMinX();
int miny = dstRaster.getMinY();
int[] bands = new int[numBands-1];
for (int i=0; i < numBands-1; i++) {
bands[i] = i;
}
dstRaster =
dstRaster.createWritableChild(minx, miny,
dstRaster.getWidth(),
dstRaster.getHeight(),
minx, miny,
bands);
}
}
filter(srcRaster, dstRaster);
}
if (needToConvert) {
// ColorModels are not the same
ColorConvertOp ccop = new ColorConvertOp(hints);
ccop.filter(dst, origDst);
}
return origDst;
}
/**
* Performs a lookup operation on a <code>Raster</code>.
* If the destination <code>Raster</code> is <code>null</code>,
* a new <code>Raster</code> will be created.
* The <code>IllegalArgumentException</code> might be thrown
* if the source <code>Raster</code> and the destination
* <code>Raster</code> do not have the same
* number of bands or if the number of arrays in the
* <code>LookupTable</code> does not meet the
* restrictions stated in the class comment above.
* @param src the source <code>Raster</code> to filter
* @param dst the destination <code>WritableRaster</code> for the
* filtered <code>src</code>
* @return the filtered <code>WritableRaster</code>.
* @throws IllegalArgumentException if the source and destinations
* rasters do not have the same number of bands, or the
* number of arrays in the <code>LookupTable</code> does
* not meet the restrictions described in the class comments.
*
*/
public final WritableRaster filter (Raster src, WritableRaster dst) {
int numBands = src.getNumBands();
int dstLength = dst.getNumBands();
int height = src.getHeight();
int width = src.getWidth();
int srcPix[] = new int[numBands];
// Create a new destination Raster, if needed
if (dst == null) {
dst = createCompatibleDestRaster(src);
}
else if (height != dst.getHeight() || width != dst.getWidth()) {
throw new
IllegalArgumentException ("Width or height of Rasters do not "+
"match");
}
dstLength = dst.getNumBands();
if (numBands != dstLength) {
throw new
IllegalArgumentException ("Number of channels in the src ("
+ numBands +
") does not match number of channels"
+ " in the destination ("
+ dstLength + ")");
}
int numComponents = ltable.getNumComponents();
if (numComponents != 1 && numComponents != src.getNumBands()) {
throw new IllegalArgumentException("Number of arrays in the "+
" lookup table ("+
numComponents+
" is not compatible with the "+
" src Raster: "+src);
}
if (ImagingLib.filter(this, src, dst) != null) {
return dst;
}
// Optimize for cases we know about
if (ltable instanceof ByteLookupTable) {
byteFilter ((ByteLookupTable) ltable, src, dst,
width, height, numBands);
}
else if (ltable instanceof ShortLookupTable) {
shortFilter ((ShortLookupTable) ltable, src, dst, width,
height, numBands);
}
else {
// Not one we recognize so do it slowly
int sminX = src.getMinX();
int sY = src.getMinY();
int dminX = dst.getMinX();
int dY = dst.getMinY();
for (int y=0; y < height; y++, sY++, dY++) {
int sX = sminX;
int dX = dminX;
for (int x=0; x < width; x++, sX++, dX++) {
// Find data for all bands at this x,y position
src.getPixel(sX, sY, srcPix);
// Lookup the data for all bands at this x,y position
ltable.lookupPixel(srcPix, srcPix);
// Put it back for all bands
dst.setPixel(dX, dY, srcPix);
}
}
}
return dst;
}
/**
* Returns the bounding box of the filtered destination image. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param src the <code>BufferedImage</code> to be filtered
* @return the bounds of the filtered definition image.
*/
public final Rectangle2D getBounds2D (BufferedImage src) {
return getBounds2D(src.getRaster());
}
/**
* Returns the bounding box of the filtered destination Raster. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param src the <code>Raster</code> to be filtered
* @return the bounds of the filtered definition <code>Raster</code>.
*/
public final Rectangle2D getBounds2D (Raster src) {
return src.getBounds();
}
/**
* Creates a zeroed destination image with the correct size and number of
* bands. If destCM is <code>null</code>, an appropriate
* <code>ColorModel</code> will be used.
* @param src Source image for the filter operation.
* @param destCM the destination's <code>ColorModel</code>, which
* can be <code>null</code>.
* @return a filtered destination <code>BufferedImage</code>.
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM) {
BufferedImage image;
int w = src.getWidth();
int h = src.getHeight();
int transferType = DataBuffer.TYPE_BYTE;
if (destCM == null) {
ColorModel cm = src.getColorModel();
Raster raster = src.getRaster();
if (cm instanceof ComponentColorModel) {
DataBuffer db = raster.getDataBuffer();
boolean hasAlpha = cm.hasAlpha();
boolean isPre = cm.isAlphaPremultiplied();
int trans = cm.getTransparency();
int[] nbits = null;
if (ltable instanceof ByteLookupTable) {
if (db.getDataType() == db.TYPE_USHORT) {
// Dst raster should be of type byte
if (hasAlpha) {
nbits = new int[2];
if (trans == cm.BITMASK) {
nbits[1] = 1;
}
else {
nbits[1] = 8;
}
}
else {
nbits = new int[1];
}
nbits[0] = 8;
}
// For byte, no need to change the cm
}
else if (ltable instanceof ShortLookupTable) {
transferType = DataBuffer.TYPE_USHORT;
if (db.getDataType() == db.TYPE_BYTE) {
if (hasAlpha) {
nbits = new int[2];
if (trans == cm.BITMASK) {
nbits[1] = 1;
}
else {
nbits[1] = 16;
}
}
else {
nbits = new int[1];
}
nbits[0] = 16;
}
}
if (nbits != null) {
cm = new ComponentColorModel(cm.getColorSpace(),
nbits, hasAlpha, isPre,
trans, transferType);
}
}
image = new BufferedImage(cm,
cm.createCompatibleWritableRaster(w, h),
cm.isAlphaPremultiplied(),
null);
}
else {
image = new BufferedImage(destCM,
destCM.createCompatibleWritableRaster(w,
h),
destCM.isAlphaPremultiplied(),
null);
}
return image;
}
/**
* Creates a zeroed-destination <code>Raster</code> with the
* correct size and number of bands, given this source.
* @param src the <code>Raster</code> to be transformed
* @return the zeroed-destination <code>Raster</code>.
*/
public WritableRaster createCompatibleDestRaster (Raster src) {
return src.createCompatibleWritableRaster();
}
/**
* Returns the location of the destination point given a
* point in the source. If <code>dstPt</code> is not
* <code>null</code>, it will be used to hold the return value.
* Since this is not a geometric operation, the <code>srcPt</code>
* will equal the <code>dstPt</code>.
* @param srcPt a <code>Point2D</code> that represents a point
* in the source image
* @param dstPt a <code>Point2D</code>that represents the location
* in the destination
* @return the <code>Point2D</code> in the destination that
* corresponds to the specified point in the source.
*/
public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
if (dstPt == null) {
dstPt = new Point2D.Float();
}
dstPt.setLocation(srcPt.getX(), srcPt.getY());
return dstPt;
}
/**
* Returns the rendering hints for this op.
* @return the <code>RenderingHints</code> object associated
* with this op.
*/
public final RenderingHints getRenderingHints() {
return hints;
}
private final void byteFilter(ByteLookupTable lookup, Raster src,
WritableRaster dst,
int width, int height, int numBands) {
int[] srcPix = null;
// Find the ref to the table and the offset
byte[][] table = lookup.getTable();
int offset = lookup.getOffset();
int tidx;
int step=1;
// Check if it is one lookup applied to all bands
if (table.length == 1) {
step=0;
}
int x;
int y;
int band;
int len = table[0].length;
// Loop through the data
for ( y=0; y < height; y++) {
tidx = 0;
for ( band=0; band < numBands; band++, tidx+=step) {
// Find data for this band, scanline
srcPix = src.getSamples(0, y, width, 1, band, srcPix);
for ( x=0; x < width; x++) {
int index = srcPix[x]-offset;
if (index < 0 || index > len) {
throw new
IllegalArgumentException("index ("+index+
"(out of range: "+
" srcPix["+x+
"]="+ srcPix[x]+
" offset="+ offset);
}
// Do the lookup
srcPix[x] = table[tidx][index];
}
// Put it back
dst.setSamples(0, y, width, 1, band, srcPix);
}
}
}
private final void shortFilter(ShortLookupTable lookup, Raster src,
WritableRaster dst,
int width, int height, int numBands) {
int band;
int[] srcPix = null;
// Find the ref to the table and the offset
short[][] table = lookup.getTable();
int offset = lookup.getOffset();
int tidx;
int step=1;
// Check if it is one lookup applied to all bands
if (table.length == 1) {
step=0;
}
int x = 0;
int y = 0;
int index;
int maxShort = (1<<16)-1;
// Loop through the data
for (y=0; y < height; y++) {
tidx = 0;
for ( band=0; band < numBands; band++, tidx+=step) {
// Find data for this band, scanline
srcPix = src.getSamples(0, y, width, 1, band, srcPix);
for ( x=0; x < width; x++) {
index = srcPix[x]-offset;
if (index < 0 || index > maxShort) {
throw new
IllegalArgumentException("index out of range "+
index+" x is "+x+
"srcPix[x]="+srcPix[x]
+" offset="+ offset);
}
// Do the lookup
srcPix[x] = table[tidx][index];
}
// Put it back
dst.setSamples(0, y, width, 1, band, srcPix);
}
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* This abstract class defines a lookup table object. ByteLookupTable
* and ShortLookupTable are subclasses, which
* contain byte and short data, respectively. A lookup table
* contains data arrays for one or more bands (or components) of an image
* (for example, separate arrays for R, G, and B),
* and it contains an offset which will be subtracted from the
* input values before indexing into the arrays. This allows an array
* smaller than the native data size to be provided for a
* constrained input. If there is only one array in the lookup
* table, it will be applied to all bands. All arrays must be the
* same size.
*
* @see ByteLookupTable
* @see ShortLookupTable
* @see LookupOp
*/
public abstract class LookupTable extends Object{
/**
* Constants
*/
int numComponents;
int offset;
int numEntries;
/**
* Constructs a new LookupTable from the number of components and an offset
* into the lookup table.
* @param offset the offset to subtract from input values before indexing
* into the data arrays for this <code>LookupTable</code>
* @param numComponents the number of data arrays in this
* <code>LookupTable</code>
* @throws IllegalArgumentException if <code>offset</code> is less than 0
* or if <code>numComponents</code> is less than 1
*/
protected LookupTable(int offset, int numComponents) {
if (offset < 0) {
throw new
IllegalArgumentException("Offset must be greater than 0");
}
if (numComponents < 1) {
throw new IllegalArgumentException("Number of components must "+
" be at least 1");
}
this.numComponents = numComponents;
this.offset = offset;
}
/**
* Returns the number of components in the lookup table.
* @return the number of components in this <code>LookupTable</code>.
*/
public int getNumComponents() {
return numComponents;
}
/**
* Returns the offset.
* @return the offset of this <code>LookupTable</code>.
*/
public int getOffset() {
return offset;
}
/**
* Returns an <code>int</code> array of components for
* one pixel. The <code>dest</code> array contains the
* result of the lookup and is returned. If dest is
* <code>null</code>, a new array is allocated. The
* source and destination can be equal.
* @param src the source array of components of one pixel
* @param dest the destination array of components for one pixel,
* translated with this <code>LookupTable</code>
* @return an <code>int</code> array of components for one
* pixel.
*/
public abstract int[] lookupPixel(int[] src, int[] dest);
}

View File

@@ -0,0 +1,571 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.awt.image.ColorModel;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
/**
* This class is an implementation of the ImageProducer interface which
* uses an array to produce pixel values for an Image. Here is an example
* which calculates a 100x100 image representing a fade from black to blue
* along the X axis and a fade from black to red along the Y axis:
* <pre>{@code
*
* int w = 100;
* int h = 100;
* int pix[] = new int[w * h];
* int index = 0;
* for (int y = 0; y < h; y++) {
* int red = (y * 255) / (h - 1);
* for (int x = 0; x < w; x++) {
* int blue = (x * 255) / (w - 1);
* pix[index++] = (255 << 24) | (red << 16) | blue;
* }
* }
* Image img = createImage(new MemoryImageSource(w, h, pix, 0, w));
*
* }</pre>
* The MemoryImageSource is also capable of managing a memory image which
* varies over time to allow animation or custom rendering. Here is an
* example showing how to set up the animation source and signal changes
* in the data (adapted from the MemoryAnimationSourceDemo by Garth Dickie):
* <pre>{@code
*
* int pixels[];
* MemoryImageSource source;
*
* public void init() {
* int width = 50;
* int height = 50;
* int size = width * height;
* pixels = new int[size];
*
* int value = getBackground().getRGB();
* for (int i = 0; i < size; i++) {
* pixels[i] = value;
* }
*
* source = new MemoryImageSource(width, height, pixels, 0, width);
* source.setAnimated(true);
* image = createImage(source);
* }
*
* public void run() {
* Thread me = Thread.currentThread( );
* me.setPriority(Thread.MIN_PRIORITY);
*
* while (true) {
* try {
* Thread.sleep(10);
* } catch( InterruptedException e ) {
* return;
* }
*
* // Modify the values in the pixels array at (x, y, w, h)
*
* // Send the new data to the interested ImageConsumers
* source.newPixels(x, y, w, h);
* }
* }
*
* }</pre>
*
* @see ImageProducer
*
* @author Jim Graham
* @author Animation capabilities inspired by the
* MemoryAnimationSource class written by Garth Dickie
*/
public class MemoryImageSource implements ImageProducer {
int width;
int height;
ColorModel model;
Object pixels;
int pixeloffset;
int pixelscan;
Hashtable properties;
Vector theConsumers = new Vector();
boolean animating;
boolean fullbuffers;
/**
* Constructs an ImageProducer object which uses an array of bytes
* to produce data for an Image object.
* @param w the width of the rectangle of pixels
* @param h the height of the rectangle of pixels
* @param cm the specified <code>ColorModel</code>
* @param pix an array of pixels
* @param off the offset into the array of where to store the
* first pixel
* @param scan the distance from one row of pixels to the next in
* the array
* @see java.awt.Component#createImage
*/
public MemoryImageSource(int w, int h, ColorModel cm,
byte[] pix, int off, int scan) {
initialize(w, h, cm, (Object) pix, off, scan, null);
}
/**
* Constructs an ImageProducer object which uses an array of bytes
* to produce data for an Image object.
* @param w the width of the rectangle of pixels
* @param h the height of the rectangle of pixels
* @param cm the specified <code>ColorModel</code>
* @param pix an array of pixels
* @param off the offset into the array of where to store the
* first pixel
* @param scan the distance from one row of pixels to the next in
* the array
* @param props a list of properties that the <code>ImageProducer</code>
* uses to process an image
* @see java.awt.Component#createImage
*/
public MemoryImageSource(int w, int h, ColorModel cm,
byte[] pix, int off, int scan,
Hashtable<?,?> props)
{
initialize(w, h, cm, (Object) pix, off, scan, props);
}
/**
* Constructs an ImageProducer object which uses an array of integers
* to produce data for an Image object.
* @param w the width of the rectangle of pixels
* @param h the height of the rectangle of pixels
* @param cm the specified <code>ColorModel</code>
* @param pix an array of pixels
* @param off the offset into the array of where to store the
* first pixel
* @param scan the distance from one row of pixels to the next in
* the array
* @see java.awt.Component#createImage
*/
public MemoryImageSource(int w, int h, ColorModel cm,
int[] pix, int off, int scan) {
initialize(w, h, cm, (Object) pix, off, scan, null);
}
/**
* Constructs an ImageProducer object which uses an array of integers
* to produce data for an Image object.
* @param w the width of the rectangle of pixels
* @param h the height of the rectangle of pixels
* @param cm the specified <code>ColorModel</code>
* @param pix an array of pixels
* @param off the offset into the array of where to store the
* first pixel
* @param scan the distance from one row of pixels to the next in
* the array
* @param props a list of properties that the <code>ImageProducer</code>
* uses to process an image
* @see java.awt.Component#createImage
*/
public MemoryImageSource(int w, int h, ColorModel cm,
int[] pix, int off, int scan,
Hashtable<?,?> props)
{
initialize(w, h, cm, (Object) pix, off, scan, props);
}
private void initialize(int w, int h, ColorModel cm,
Object pix, int off, int scan, Hashtable props) {
width = w;
height = h;
model = cm;
pixels = pix;
pixeloffset = off;
pixelscan = scan;
if (props == null) {
props = new Hashtable();
}
properties = props;
}
/**
* Constructs an ImageProducer object which uses an array of integers
* in the default RGB ColorModel to produce data for an Image object.
* @param w the width of the rectangle of pixels
* @param h the height of the rectangle of pixels
* @param pix an array of pixels
* @param off the offset into the array of where to store the
* first pixel
* @param scan the distance from one row of pixels to the next in
* the array
* @see java.awt.Component#createImage
* @see ColorModel#getRGBdefault
*/
public MemoryImageSource(int w, int h, int pix[], int off, int scan) {
initialize(w, h, ColorModel.getRGBdefault(),
(Object) pix, off, scan, null);
}
/**
* Constructs an ImageProducer object which uses an array of integers
* in the default RGB ColorModel to produce data for an Image object.
* @param w the width of the rectangle of pixels
* @param h the height of the rectangle of pixels
* @param pix an array of pixels
* @param off the offset into the array of where to store the
* first pixel
* @param scan the distance from one row of pixels to the next in
* the array
* @param props a list of properties that the <code>ImageProducer</code>
* uses to process an image
* @see java.awt.Component#createImage
* @see ColorModel#getRGBdefault
*/
public MemoryImageSource(int w, int h, int pix[], int off, int scan,
Hashtable<?,?> props)
{
initialize(w, h, ColorModel.getRGBdefault(),
(Object) pix, off, scan, props);
}
/**
* Adds an ImageConsumer to the list of consumers interested in
* data for this image.
* @param ic the specified <code>ImageConsumer</code>
* @throws NullPointerException if the specified
* <code>ImageConsumer</code> is null
* @see ImageConsumer
*/
public synchronized void addConsumer(ImageConsumer ic) {
if (theConsumers.contains(ic)) {
return;
}
theConsumers.addElement(ic);
try {
initConsumer(ic);
sendPixels(ic, 0, 0, width, height);
if (isConsumer(ic)) {
ic.imageComplete(animating
? ImageConsumer.SINGLEFRAMEDONE
: ImageConsumer.STATICIMAGEDONE);
if (!animating && isConsumer(ic)) {
ic.imageComplete(ImageConsumer.IMAGEERROR);
removeConsumer(ic);
}
}
} catch (Exception e) {
if (isConsumer(ic)) {
ic.imageComplete(ImageConsumer.IMAGEERROR);
}
}
}
/**
* Determines if an ImageConsumer is on the list of consumers currently
* interested in data for this image.
* @param ic the specified <code>ImageConsumer</code>
* @return <code>true</code> if the <code>ImageConsumer</code>
* is on the list; <code>false</code> otherwise.
* @see ImageConsumer
*/
public synchronized boolean isConsumer(ImageConsumer ic) {
return theConsumers.contains(ic);
}
/**
* Removes an ImageConsumer from the list of consumers interested in
* data for this image.
* @param ic the specified <code>ImageConsumer</code>
* @see ImageConsumer
*/
public synchronized void removeConsumer(ImageConsumer ic) {
theConsumers.removeElement(ic);
}
/**
* Adds an ImageConsumer to the list of consumers interested in
* data for this image and immediately starts delivery of the
* image data through the ImageConsumer interface.
* @param ic the specified <code>ImageConsumer</code>
* image data through the ImageConsumer interface.
* @see ImageConsumer
*/
public void startProduction(ImageConsumer ic) {
addConsumer(ic);
}
/**
* Requests that a given ImageConsumer have the image data delivered
* one more time in top-down, left-right order.
* @param ic the specified <code>ImageConsumer</code>
* @see ImageConsumer
*/
public void requestTopDownLeftRightResend(ImageConsumer ic) {
// Ignored. The data is either single frame and already in TDLR
// format or it is multi-frame and TDLR resends aren't critical.
}
/**
* Changes this memory image into a multi-frame animation or a
* single-frame static image depending on the animated parameter.
* <p>This method should be called immediately after the
* MemoryImageSource is constructed and before an image is
* created with it to ensure that all ImageConsumers will
* receive the correct multi-frame data. If an ImageConsumer
* is added to this ImageProducer before this flag is set then
* that ImageConsumer will see only a snapshot of the pixel
* data that was available when it connected.
* @param animated <code>true</code> if the image is a
* multi-frame animation
*/
public synchronized void setAnimated(boolean animated) {
this.animating = animated;
if (!animating) {
Enumeration enum_ = theConsumers.elements();
while (enum_.hasMoreElements()) {
ImageConsumer ic = (ImageConsumer) enum_.nextElement();
ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
if (isConsumer(ic)) {
ic.imageComplete(ImageConsumer.IMAGEERROR);
}
}
theConsumers.removeAllElements();
}
}
/**
* Specifies whether this animated memory image should always be
* updated by sending the complete buffer of pixels whenever
* there is a change.
* This flag is ignored if the animation flag is not turned on
* through the setAnimated() method.
* <p>This method should be called immediately after the
* MemoryImageSource is constructed and before an image is
* created with it to ensure that all ImageConsumers will
* receive the correct pixel delivery hints.
* @param fullbuffers <code>true</code> if the complete pixel
* buffer should always
* be sent
* @see #setAnimated
*/
public synchronized void setFullBufferUpdates(boolean fullbuffers) {
if (this.fullbuffers == fullbuffers) {
return;
}
this.fullbuffers = fullbuffers;
if (animating) {
Enumeration enum_ = theConsumers.elements();
while (enum_.hasMoreElements()) {
ImageConsumer ic = (ImageConsumer) enum_.nextElement();
ic.setHints(fullbuffers
? (ImageConsumer.TOPDOWNLEFTRIGHT |
ImageConsumer.COMPLETESCANLINES)
: ImageConsumer.RANDOMPIXELORDER);
}
}
}
/**
* Sends a whole new buffer of pixels to any ImageConsumers that
* are currently interested in the data for this image and notify
* them that an animation frame is complete.
* This method only has effect if the animation flag has been
* turned on through the setAnimated() method.
* @see #newPixels(int, int, int, int, boolean)
* @see ImageConsumer
* @see #setAnimated
*/
public void newPixels() {
newPixels(0, 0, width, height, true);
}
/**
* Sends a rectangular region of the buffer of pixels to any
* ImageConsumers that are currently interested in the data for
* this image and notify them that an animation frame is complete.
* This method only has effect if the animation flag has been
* turned on through the setAnimated() method.
* If the full buffer update flag was turned on with the
* setFullBufferUpdates() method then the rectangle parameters
* will be ignored and the entire buffer will always be sent.
* @param x the x coordinate of the upper left corner of the rectangle
* of pixels to be sent
* @param y the y coordinate of the upper left corner of the rectangle
* of pixels to be sent
* @param w the width of the rectangle of pixels to be sent
* @param h the height of the rectangle of pixels to be sent
* @see #newPixels(int, int, int, int, boolean)
* @see ImageConsumer
* @see #setAnimated
* @see #setFullBufferUpdates
*/
public synchronized void newPixels(int x, int y, int w, int h) {
newPixels(x, y, w, h, true);
}
/**
* Sends a rectangular region of the buffer of pixels to any
* ImageConsumers that are currently interested in the data for
* this image.
* If the framenotify parameter is true then the consumers are
* also notified that an animation frame is complete.
* This method only has effect if the animation flag has been
* turned on through the setAnimated() method.
* If the full buffer update flag was turned on with the
* setFullBufferUpdates() method then the rectangle parameters
* will be ignored and the entire buffer will always be sent.
* @param x the x coordinate of the upper left corner of the rectangle
* of pixels to be sent
* @param y the y coordinate of the upper left corner of the rectangle
* of pixels to be sent
* @param w the width of the rectangle of pixels to be sent
* @param h the height of the rectangle of pixels to be sent
* @param framenotify <code>true</code> if the consumers should be sent a
* {@link ImageConsumer#SINGLEFRAMEDONE SINGLEFRAMEDONE} notification
* @see ImageConsumer
* @see #setAnimated
* @see #setFullBufferUpdates
*/
public synchronized void newPixels(int x, int y, int w, int h,
boolean framenotify) {
if (animating) {
if (fullbuffers) {
x = y = 0;
w = width;
h = height;
} else {
if (x < 0) {
w += x;
x = 0;
}
if (x + w > width) {
w = width - x;
}
if (y < 0) {
h += y;
y = 0;
}
if (y + h > height) {
h = height - y;
}
}
if ((w <= 0 || h <= 0) && !framenotify) {
return;
}
Enumeration enum_ = theConsumers.elements();
while (enum_.hasMoreElements()) {
ImageConsumer ic = (ImageConsumer) enum_.nextElement();
if (w > 0 && h > 0) {
sendPixels(ic, x, y, w, h);
}
if (framenotify && isConsumer(ic)) {
ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
}
}
}
}
/**
* Changes to a new byte array to hold the pixels for this image.
* If the animation flag has been turned on through the setAnimated()
* method, then the new pixels will be immediately delivered to any
* ImageConsumers that are currently interested in the data for
* this image.
* @param newpix the new pixel array
* @param newmodel the specified <code>ColorModel</code>
* @param offset the offset into the array
* @param scansize the distance from one row of pixels to the next in
* the array
* @see #newPixels(int, int, int, int, boolean)
* @see #setAnimated
*/
public synchronized void newPixels(byte[] newpix, ColorModel newmodel,
int offset, int scansize) {
this.pixels = newpix;
this.model = newmodel;
this.pixeloffset = offset;
this.pixelscan = scansize;
newPixels();
}
/**
* Changes to a new int array to hold the pixels for this image.
* If the animation flag has been turned on through the setAnimated()
* method, then the new pixels will be immediately delivered to any
* ImageConsumers that are currently interested in the data for
* this image.
* @param newpix the new pixel array
* @param newmodel the specified <code>ColorModel</code>
* @param offset the offset into the array
* @param scansize the distance from one row of pixels to the next in
* the array
* @see #newPixels(int, int, int, int, boolean)
* @see #setAnimated
*/
public synchronized void newPixels(int[] newpix, ColorModel newmodel,
int offset, int scansize) {
this.pixels = newpix;
this.model = newmodel;
this.pixeloffset = offset;
this.pixelscan = scansize;
newPixels();
}
private void initConsumer(ImageConsumer ic) {
if (isConsumer(ic)) {
ic.setDimensions(width, height);
}
if (isConsumer(ic)) {
ic.setProperties(properties);
}
if (isConsumer(ic)) {
ic.setColorModel(model);
}
if (isConsumer(ic)) {
ic.setHints(animating
? (fullbuffers
? (ImageConsumer.TOPDOWNLEFTRIGHT |
ImageConsumer.COMPLETESCANLINES)
: ImageConsumer.RANDOMPIXELORDER)
: (ImageConsumer.TOPDOWNLEFTRIGHT |
ImageConsumer.COMPLETESCANLINES |
ImageConsumer.SINGLEPASS |
ImageConsumer.SINGLEFRAME));
}
}
private void sendPixels(ImageConsumer ic, int x, int y, int w, int h) {
int off = pixeloffset + pixelscan * y + x;
if (isConsumer(ic)) {
if (pixels instanceof byte[]) {
ic.setPixels(x, y, w, h, model,
((byte[]) pixels), off, pixelscan);
} else {
ic.setPixels(x, y, w, h, model,
((int[]) pixels), off, pixelscan);
}
}
}
}

View File

@@ -0,0 +1,699 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
/**
* The <code>MultiPixelPackedSampleModel</code> class represents
* one-banded images and can pack multiple one-sample
* pixels into one data element. Pixels are not allowed to span data elements.
* The data type can be DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
* or DataBuffer.TYPE_INT. Each pixel must be a power of 2 number of bits
* and a power of 2 number of pixels must fit exactly in one data element.
* Pixel bit stride is equal to the number of bits per pixel. Scanline
* stride is in data elements and the last several data elements might be
* padded with unused pixels. Data bit offset is the offset in bits from
* the beginning of the {@link DataBuffer} to the first pixel and must be
* a multiple of pixel bit stride.
* <p>
* The following code illustrates extracting the bits for pixel
* <code>x,&nbsp;y</code> from <code>DataBuffer</code> <code>data</code>
* and storing the pixel data in data elements of type
* <code>dataType</code>:
* <pre>{@code
* int dataElementSize = DataBuffer.getDataTypeSize(dataType);
* int bitnum = dataBitOffset + x*pixelBitStride;
* int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
* int shift = dataElementSize - (bitnum & (dataElementSize-1))
* - pixelBitStride;
* int pixel = (element >> shift) & ((1 << pixelBitStride) - 1);
* }</pre>
*/
public class MultiPixelPackedSampleModel extends SampleModel
{
/** The number of bits from one pixel to the next. */
int pixelBitStride;
/** Bitmask that extracts the rightmost pixel of a data element. */
int bitMask;
/**
* The number of pixels that fit in a data element. Also used
* as the number of bits per pixel.
*/
int pixelsPerDataElement;
/** The size of a data element in bits. */
int dataElementSize;
/** The bit offset into the data array where the first pixel begins.
*/
int dataBitOffset;
/** ScanlineStride of the data buffer described in data array elements. */
int scanlineStride;
/**
* Constructs a <code>MultiPixelPackedSampleModel</code> with the
* specified data type, width, height and number of bits per pixel.
* @param dataType the data type for storing samples
* @param w the width, in pixels, of the region of
* image data described
* @param h the height, in pixels, of the region of
* image data described
* @param numberOfBits the number of bits per pixel
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public MultiPixelPackedSampleModel(int dataType,
int w,
int h,
int numberOfBits) {
this(dataType,w,h,
numberOfBits,
(w*numberOfBits+DataBuffer.getDataTypeSize(dataType)-1)/
DataBuffer.getDataTypeSize(dataType),
0);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
}
/**
* Constructs a <code>MultiPixelPackedSampleModel</code> with
* specified data type, width, height, number of bits per pixel,
* scanline stride and data bit offset.
* @param dataType the data type for storing samples
* @param w the width, in pixels, of the region of
* image data described
* @param h the height, in pixels, of the region of
* image data described
* @param numberOfBits the number of bits per pixel
* @param scanlineStride the line stride of the image data
* @param dataBitOffset the data bit offset for the region of image
* data described
* @exception RasterFormatException if the number of bits per pixel
* is not a power of 2 or if a power of 2 number of
* pixels do not fit in one data element.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public MultiPixelPackedSampleModel(int dataType, int w, int h,
int numberOfBits,
int scanlineStride,
int dataBitOffset) {
super(dataType, w, h, 1);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
this.dataType = dataType;
this.pixelBitStride = numberOfBits;
this.scanlineStride = scanlineStride;
this.dataBitOffset = dataBitOffset;
this.dataElementSize = DataBuffer.getDataTypeSize(dataType);
this.pixelsPerDataElement = dataElementSize/numberOfBits;
if (pixelsPerDataElement*numberOfBits != dataElementSize) {
throw new RasterFormatException("MultiPixelPackedSampleModel " +
"does not allow pixels to " +
"span data element boundaries");
}
this.bitMask = (1 << numberOfBits) - 1;
}
/**
* Creates a new <code>MultiPixelPackedSampleModel</code> with the
* specified width and height. The new
* <code>MultiPixelPackedSampleModel</code> has the
* same storage data type and number of bits per pixel as this
* <code>MultiPixelPackedSampleModel</code>.
* @param w the specified width
* @param h the specified height
* @return a {@link SampleModel} with the specified width and height
* and with the same storage data type and number of bits per pixel
* as this <code>MultiPixelPackedSampleModel</code>.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
SampleModel sampleModel =
new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
return sampleModel;
}
/**
* Creates a <code>DataBuffer</code> that corresponds to this
* <code>MultiPixelPackedSampleModel</code>. The
* <code>DataBuffer</code> object's data type and size
* is consistent with this <code>MultiPixelPackedSampleModel</code>.
* The <code>DataBuffer</code> has a single bank.
* @return a <code>DataBuffer</code> with the same data type and
* size as this <code>MultiPixelPackedSampleModel</code>.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = (int)scanlineStride*height;
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size+(dataBitOffset+7)/8);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size+(dataBitOffset+31)/32);
break;
}
return dataBuffer;
}
/**
* Returns the number of data elements needed to transfer one pixel
* via the {@link #getDataElements} and {@link #setDataElements}
* methods. For a <code>MultiPixelPackedSampleModel</code>, this is
* one.
* @return the number of data elements.
*/
public int getNumDataElements() {
return 1;
}
/**
* Returns the number of bits per sample for all bands.
* @return the number of bits per sample.
*/
public int[] getSampleSize() {
int sampleSize[] = {pixelBitStride};
return sampleSize;
}
/**
* Returns the number of bits per sample for the specified band.
* @param band the specified band
* @return the number of bits per sample for the specified band.
*/
public int getSampleSize(int band) {
return pixelBitStride;
}
/**
* Returns the offset of pixel (x,&nbsp;y) in data array elements.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @return the offset of the specified pixel.
*/
public int getOffset(int x, int y) {
int offset = y * scanlineStride;
offset += (x*pixelBitStride+dataBitOffset)/dataElementSize;
return offset;
}
/**
* Returns the offset, in bits, into the data element in which it is
* stored for the <code>x</code>th pixel of a scanline.
* This offset is the same for all scanlines.
* @param x the specified pixel
* @return the bit offset of the specified pixel.
*/
public int getBitOffset(int x){
return (x*pixelBitStride+dataBitOffset)%dataElementSize;
}
/**
* Returns the scanline stride.
* @return the scanline stride of this
* <code>MultiPixelPackedSampleModel</code>.
*/
public int getScanlineStride() {
return scanlineStride;
}
/**
* Returns the pixel bit stride in bits. This value is the same as
* the number of bits per pixel.
* @return the <code>pixelBitStride</code> of this
* <code>MultiPixelPackedSampleModel</code>.
*/
public int getPixelBitStride() {
return pixelBitStride;
}
/**
* Returns the data bit offset in bits.
* @return the <code>dataBitOffset</code> of this
* <code>MultiPixelPackedSampleModel</code>.
*/
public int getDataBitOffset() {
return dataBitOffset;
}
/**
* Returns the TransferType used to transfer pixels by way of the
* <code>getDataElements</code> and <code>setDataElements</code>
* methods. The TransferType might or might not be the same as the
* storage DataType. The TransferType is one of
* DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
* or DataBuffer.TYPE_INT.
* @return the transfertype.
*/
public int getTransferType() {
if (pixelBitStride > 16)
return DataBuffer.TYPE_INT;
else if (pixelBitStride > 8)
return DataBuffer.TYPE_USHORT;
else
return DataBuffer.TYPE_BYTE;
}
/**
* Creates a new <code>MultiPixelPackedSampleModel</code> with a
* subset of the bands of this
* <code>MultiPixelPackedSampleModel</code>. Since a
* <code>MultiPixelPackedSampleModel</code> only has one band, the
* bands argument must have a length of one and indicate the zeroth
* band.
* @param bands the specified bands
* @return a new <code>SampleModel</code> with a subset of bands of
* this <code>MultiPixelPackedSampleModel</code>.
* @exception RasterFormatException if the number of bands requested
* is not one.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createSubsetSampleModel(int bands[]) {
if (bands != null) {
if (bands.length != 1)
throw new RasterFormatException("MultiPixelPackedSampleModel has "
+ "only one band.");
}
SampleModel sm = createCompatibleSampleModel(width, height);
return sm;
}
/**
* Returns as <code>int</code> the sample in a specified band for the
* pixel located at (x,&nbsp;y). An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param b the band to return, which is assumed to be 0
* @param data the <code>DataBuffer</code> containing the image
* data
* @return the specified band containing the sample of the specified
* pixel.
* @exception ArrayIndexOutOfBoundsException if the specified
* coordinates are not in bounds.
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data) {
// 'b' must be 0
if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
(b != 0)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int bitnum = dataBitOffset + x*pixelBitStride;
int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
return (element >> shift) & bitMask;
}
/**
* Sets a sample in the specified band for the pixel located at
* (x,&nbsp;y) in the <code>DataBuffer</code> using an
* <code>int</code> for input.
* An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param b the band to return, which is assumed to be 0
* @param s the input sample as an <code>int</code>
* @param data the <code>DataBuffer</code> where image data is stored
* @exception ArrayIndexOutOfBoundsException if the coordinates are
* not in bounds.
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b, int s,
DataBuffer data) {
// 'b' must be 0
if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
(b != 0)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int bitnum = dataBitOffset + x * pixelBitStride;
int index = y * scanlineStride + (bitnum / dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = data.getElem(index);
element &= ~(bitMask << shift);
element |= (s & bitMask) << shift;
data.setElem(index,element);
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a <code>MultiPixelPackedSampleModel</code>,
* the array has one element, and the type is the smallest of
* DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
* that can hold a single pixel. Generally, <code>obj</code>
* should be passed in as <code>null</code>, so that the
* <code>Object</code> is created automatically and is the
* correct primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is
* described by <code>MultiPixelPackedSampleModel</code>
* <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
* whose storage layout is described by
* <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
* The transfer is generally more efficient than using
* <code>getPixel</code> or <code>setPixel</code>.
* <pre>
* MultiPixelPackedSampleModel mppsm1, mppsm2;
* DataBufferInt db1, db2;
* mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using <code>getDataElements</code> or <code>setDataElements</code>
* to transfer between two <code>DataBuffer/SampleModel</code> pairs
* is legitimate if the <code>SampleModels</code> have the same number
* of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* If <code>obj</code> is not <code>null</code>, it should be a
* primitive array of type TransferType. Otherwise, a
* <code>ClassCastException</code> is thrown. An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds, or if <code>obj</code> is not
* <code>null</code> and is not large enough to hold the pixel data.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param obj a primitive array in which to return the pixel data or
* <code>null</code>.
* @param data the <code>DataBuffer</code> containing the image data.
* @return an <code>Object</code> containing data for the specified
* pixel.
* @exception ClassCastException if <code>obj</code> is not a
* primitive array of type TransferType or is not <code>null</code>
* @exception ArrayIndexOutOfBoundsException if the coordinates are
* not in bounds, or if <code>obj</code> is not <code>null</code> or
* not large enough to hold the pixel data
* @see #setDataElements(int, int, Object, DataBuffer)
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int bitnum = dataBitOffset + x*pixelBitStride;
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = 0;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null)
bdata = new byte[1];
else
bdata = (byte[])obj;
element = data.getElem(y*scanlineStride +
bitnum/dataElementSize);
bdata[0] = (byte)((element >> shift) & bitMask);
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
short[] sdata;
if (obj == null)
sdata = new short[1];
else
sdata = (short[])obj;
element = data.getElem(y*scanlineStride +
bitnum/dataElementSize);
sdata[0] = (short)((element >> shift) & bitMask);
obj = (Object)sdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null)
idata = new int[1];
else
idata = (int[])obj;
element = data.getElem(y*scanlineStride +
bitnum/dataElementSize);
idata[0] = (element >> shift) & bitMask;
obj = (Object)idata;
break;
}
return obj;
}
/**
* Returns the specified single band pixel in the first element
* of an <code>int</code> array.
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param iArray the array containing the pixel to be returned or
* <code>null</code>
* @param data the <code>DataBuffer</code> where image data is stored
* @return an array containing the specified pixel.
* @exception ArrayIndexOutOfBoundsException if the coordinates
* are not in bounds
* @see #setPixel(int, int, int[], DataBuffer)
*/
public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixels[];
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int [numBands];
}
int bitnum = dataBitOffset + x*pixelBitStride;
int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
pixels[0] = (element >> shift) & bitMask;
return pixels;
}
/**
* Sets the data for a single pixel in the specified
* <code>DataBuffer</code> from a primitive array of type
* TransferType. For a <code>MultiPixelPackedSampleModel</code>,
* only the first element of the array holds valid data,
* and the type must be the smallest of
* DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
* that can hold a single pixel.
* <p>
* The following code illustrates transferring data for one pixel from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is
* described by <code>MultiPixelPackedSampleModel</code>
* <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
* whose storage layout is described by
* <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
* The transfer is generally more efficient than using
* <code>getPixel</code> or <code>setPixel</code>.
* <pre>
* MultiPixelPackedSampleModel mppsm1, mppsm2;
* DataBufferInt db1, db2;
* mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using <code>getDataElements</code> or <code>setDataElements</code> to
* transfer between two <code>DataBuffer/SampleModel</code> pairs is
* legitimate if the <code>SampleModel</code> objects have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* <code>obj</code> must be a primitive array of type TransferType.
* Otherwise, a <code>ClassCastException</code> is thrown. An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds, or if <code>obj</code> is not large
* enough to hold the pixel data.
* @param x the X coordinate of the pixel location
* @param y the Y coordinate of the pixel location
* @param obj a primitive array containing pixel data
* @param data the <code>DataBuffer</code> containing the image data
* @see #getDataElements(int, int, Object, DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int bitnum = dataBitOffset + x * pixelBitStride;
int index = y * scanlineStride + (bitnum / dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = data.getElem(index);
element &= ~(bitMask << shift);
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
element |= ( ((int)(barray[0])&0xff) & bitMask) << shift;
data.setElem(index, element);
break;
case DataBuffer.TYPE_USHORT:
short[] sarray = (short[])obj;
element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift;
data.setElem(index, element);
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
element |= (iarray[0] & bitMask) << shift;
data.setElem(index, element);
break;
}
}
/**
* Sets a pixel in the <code>DataBuffer</code> using an
* <code>int</code> array for input.
* <code>ArrayIndexOutOfBoundsException</code> is thrown if
* the coordinates are not in bounds.
* @param x the X coordinate of the pixel location
* @param y the Y coordinate of the pixel location
* @param iArray the input pixel in an <code>int</code> array
* @param data the <code>DataBuffer</code> containing the image data
* @see #getPixel(int, int, int[], DataBuffer)
*/
public void setPixel(int x, int y, int[] iArray, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int bitnum = dataBitOffset + x * pixelBitStride;
int index = y * scanlineStride + (bitnum / dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = data.getElem(index);
element &= ~(bitMask << shift);
element |= (iArray[0] & bitMask) << shift;
data.setElem(index,element);
}
public boolean equals(Object o) {
if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
return false;
}
MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel)o;
return this.width == that.width &&
this.height == that.height &&
this.numBands == that.numBands &&
this.dataType == that.dataType &&
this.pixelBitStride == that.pixelBitStride &&
this.bitMask == that.bitMask &&
this.pixelsPerDataElement == that.pixelsPerDataElement &&
this.dataElementSize == that.dataElementSize &&
this.dataBitOffset == that.dataBitOffset &&
this.scanlineStride == that.scanlineStride;
}
// If we implement equals() we must also implement hashCode
public int hashCode() {
int hash = 0;
hash = width;
hash <<= 8;
hash ^= height;
hash <<= 8;
hash ^= numBands;
hash <<= 8;
hash ^= dataType;
hash <<= 8;
hash ^= pixelBitStride;
hash <<= 8;
hash ^= bitMask;
hash <<= 8;
hash ^= pixelsPerDataElement;
hash <<= 8;
hash ^= dataElementSize;
hash <<= 8;
hash ^= dataBitOffset;
hash <<= 8;
hash ^= scanlineStride;
return hash;
}
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
/**
* The <code>PackedColorModel</code> class is an abstract
* {@link ColorModel} class that works with pixel values which represent
* color and alpha information as separate samples and which pack all
* samples for a single pixel into a single int, short, or byte quantity.
* This class can be used with an arbitrary {@link ColorSpace}. The number of
* color samples in the pixel values must be the same as the number of color
* components in the <code>ColorSpace</code>. There can be a single alpha
* sample. The array length is always 1 for those methods that use a
* primitive array pixel representation of type <code>transferType</code>.
* The transfer types supported are DataBuffer.TYPE_BYTE,
* DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
* Color and alpha samples are stored in the single element of the array
* in bits indicated by bit masks. Each bit mask must be contiguous and
* masks must not overlap. The same masks apply to the single int
* pixel representation used by other methods. The correspondence of
* masks and color/alpha samples is as follows:
* <ul>
* <li> Masks are identified by indices running from 0 through
* {@link ColorModel#getNumComponents() getNumComponents}&nbsp;-&nbsp;1.
* <li> The first
* {@link ColorModel#getNumColorComponents() getNumColorComponents}
* indices refer to color samples.
* <li> If an alpha sample is present, it corresponds the last index.
* <li> The order of the color indices is specified
* by the <code>ColorSpace</code>. Typically, this reflects the name of
* the color space type (for example, TYPE_RGB), index 0
* corresponds to red, index 1 to green, and index 2 to blue.
* </ul>
* <p>
* The translation from pixel values to color/alpha components for
* display or processing purposes is a one-to-one correspondence of
* samples to components.
* A <code>PackedColorModel</code> is typically used with image data
* that uses masks to define packed samples. For example, a
* <code>PackedColorModel</code> can be used in conjunction with a
* {@link SinglePixelPackedSampleModel} to construct a
* {@link BufferedImage}. Normally the masks used by the
* {@link SampleModel} and the <code>ColorModel</code> would be the same.
* However, if they are different, the color interpretation of pixel data is
* done according to the masks of the <code>ColorModel</code>.
* <p>
* A single <code>int</code> pixel representation is valid for all objects
* of this class since it is always possible to represent pixel values
* used with this class in a single <code>int</code>. Therefore, methods
* that use this representation do not throw an
* <code>IllegalArgumentException</code> due to an invalid pixel value.
* <p>
* A subclass of <code>PackedColorModel</code> is {@link DirectColorModel},
* which is similar to an X11 TrueColor visual.
*
* @see DirectColorModel
* @see SinglePixelPackedSampleModel
* @see BufferedImage
*/
public abstract class PackedColorModel extends ColorModel {
int[] maskArray;
int[] maskOffsets;
float[] scaleFactors;
/**
* Constructs a <code>PackedColorModel</code> from a color mask array,
* which specifies which bits in an <code>int</code> pixel representation
* contain each of the color samples, and an alpha mask. Color
* components are in the specified <code>ColorSpace</code>. The length of
* <code>colorMaskArray</code> should be the number of components in
* the <code>ColorSpace</code>. All of the bits in each mask
* must be contiguous and fit in the specified number of least significant
* bits of an <code>int</code> pixel representation. If the
* <code>alphaMask</code> is 0, there is no alpha. If there is alpha,
* the <code>boolean</code> <code>isAlphaPremultiplied</code> specifies
* how to interpret color and alpha samples in pixel values. If the
* <code>boolean</code> is <code>true</code>, color samples are assumed
* to have been multiplied by the alpha sample. The transparency,
* <code>trans</code>, specifies what alpha values can be represented
* by this color model. The transfer type is the type of primitive
* array used to represent pixel values.
* @param space the specified <code>ColorSpace</code>
* @param bits the number of bits in the pixel values
* @param colorMaskArray array that specifies the masks representing
* the bits of the pixel values that represent the color
* components
* @param alphaMask specifies the mask representing
* the bits of the pixel values that represent the alpha
* component
* @param isAlphaPremultiplied <code>true</code> if color samples are
* premultiplied by the alpha sample; <code>false</code> otherwise
* @param trans specifies the alpha value that can be represented by
* this color model
* @param transferType the type of array used to represent pixel values
* @throws IllegalArgumentException if <code>bits</code> is less than
* 1 or greater than 32
*/
public PackedColorModel (ColorSpace space, int bits,
int[] colorMaskArray, int alphaMask,
boolean isAlphaPremultiplied,
int trans, int transferType) {
super(bits, PackedColorModel.createBitsArray(colorMaskArray,
alphaMask),
space, (alphaMask == 0 ? false : true),
isAlphaPremultiplied, trans, transferType);
if (bits < 1 || bits > 32) {
throw new IllegalArgumentException("Number of bits must be between"
+" 1 and 32.");
}
maskArray = new int[numComponents];
maskOffsets = new int[numComponents];
scaleFactors = new float[numComponents];
for (int i=0; i < numColorComponents; i++) {
// Get the mask offset and #bits
DecomposeMask(colorMaskArray[i], i, space.getName(i));
}
if (alphaMask != 0) {
DecomposeMask(alphaMask, numColorComponents, "alpha");
if (nBits[numComponents-1] == 1) {
transparency = Transparency.BITMASK;
}
}
}
/**
* Constructs a <code>PackedColorModel</code> from the specified
* masks which indicate which bits in an <code>int</code> pixel
* representation contain the alpha, red, green and blue color samples.
* Color components are in the specified <code>ColorSpace</code>, which
* must be of type ColorSpace.TYPE_RGB. All of the bits in each
* mask must be contiguous and fit in the specified number of
* least significant bits of an <code>int</code> pixel representation. If
* <code>amask</code> is 0, there is no alpha. If there is alpha,
* the <code>boolean</code> <code>isAlphaPremultiplied</code>
* specifies how to interpret color and alpha samples
* in pixel values. If the <code>boolean</code> is <code>true</code>,
* color samples are assumed to have been multiplied by the alpha sample.
* The transparency, <code>trans</code>, specifies what alpha values
* can be represented by this color model.
* The transfer type is the type of primitive array used to represent
* pixel values.
* @param space the specified <code>ColorSpace</code>
* @param bits the number of bits in the pixel values
* @param rmask specifies the mask representing
* the bits of the pixel values that represent the red
* color component
* @param gmask specifies the mask representing
* the bits of the pixel values that represent the green
* color component
* @param bmask specifies the mask representing
* the bits of the pixel values that represent
* the blue color component
* @param amask specifies the mask representing
* the bits of the pixel values that represent
* the alpha component
* @param isAlphaPremultiplied <code>true</code> if color samples are
* premultiplied by the alpha sample; <code>false</code> otherwise
* @param trans specifies the alpha value that can be represented by
* this color model
* @param transferType the type of array used to represent pixel values
* @throws IllegalArgumentException if <code>space</code> is not a
* TYPE_RGB space
* @see ColorSpace
*/
public PackedColorModel(ColorSpace space, int bits, int rmask, int gmask,
int bmask, int amask,
boolean isAlphaPremultiplied,
int trans, int transferType) {
super (bits, PackedColorModel.createBitsArray(rmask, gmask, bmask,
amask),
space, (amask == 0 ? false : true),
isAlphaPremultiplied, trans, transferType);
if (space.getType() != ColorSpace.TYPE_RGB) {
throw new IllegalArgumentException("ColorSpace must be TYPE_RGB.");
}
maskArray = new int[numComponents];
maskOffsets = new int[numComponents];
scaleFactors = new float[numComponents];
DecomposeMask(rmask, 0, "red");
DecomposeMask(gmask, 1, "green");
DecomposeMask(bmask, 2, "blue");
if (amask != 0) {
DecomposeMask(amask, 3, "alpha");
if (nBits[3] == 1) {
transparency = Transparency.BITMASK;
}
}
}
/**
* Returns the mask indicating which bits in a pixel
* contain the specified color/alpha sample. For color
* samples, <code>index</code> corresponds to the placement of color
* sample names in the color space. Thus, an <code>index</code>
* equal to 0 for a CMYK ColorSpace would correspond to
* Cyan and an <code>index</code> equal to 1 would correspond to
* Magenta. If there is alpha, the alpha <code>index</code> would be:
* <pre>
* alphaIndex = numComponents() - 1;
* </pre>
* @param index the specified color or alpha sample
* @return the mask, which indicates which bits of the <code>int</code>
* pixel representation contain the color or alpha sample specified
* by <code>index</code>.
* @throws ArrayIndexOutOfBoundsException if <code>index</code> is
* greater than the number of components minus 1 in this
* <code>PackedColorModel</code> or if <code>index</code> is
* less than zero
*/
final public int getMask(int index) {
return maskArray[index];
}
/**
* Returns a mask array indicating which bits in a pixel
* contain the color and alpha samples.
* @return the mask array , which indicates which bits of the
* <code>int</code> pixel
* representation contain the color or alpha samples.
*/
final public int[] getMasks() {
return (int[]) maskArray.clone();
}
/*
* A utility function to compute the mask offset and scalefactor,
* store these and the mask in instance arrays, and verify that
* the mask fits in the specified pixel size.
*/
private void DecomposeMask(int mask, int idx, String componentName) {
int off = 0;
int count = nBits[idx];
// Store the mask
maskArray[idx] = mask;
// Now find the shift
if (mask != 0) {
while ((mask & 1) == 0) {
mask >>>= 1;
off++;
}
}
if (off + count > pixel_bits) {
throw new IllegalArgumentException(componentName + " mask "+
Integer.toHexString(maskArray[idx])+
" overflows pixel (expecting "+
pixel_bits+" bits");
}
maskOffsets[idx] = off;
if (count == 0) {
// High enough to scale any 0-ff value down to 0.0, but not
// high enough to get Infinity when scaling back to pixel bits
scaleFactors[idx] = 256.0f;
} else {
scaleFactors[idx] = 255.0f / ((1 << count) - 1);
}
}
/**
* Creates a <code>SampleModel</code> with the specified width and
* height that has a data layout compatible with this
* <code>ColorModel</code>.
* @param w the width (in pixels) of the region of the image data
* described
* @param h the height (in pixels) of the region of the image data
* described
* @return the newly created <code>SampleModel</code>.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
* @see SampleModel
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
return new SinglePixelPackedSampleModel(transferType, w, h,
maskArray);
}
/**
* Checks if the specified <code>SampleModel</code> is compatible
* with this <code>ColorModel</code>. If <code>sm</code> is
* <code>null</code>, this method returns <code>false</code>.
* @param sm the specified <code>SampleModel</code>,
* or <code>null</code>
* @return <code>true</code> if the specified <code>SampleModel</code>
* is compatible with this <code>ColorModel</code>;
* <code>false</code> otherwise.
* @see SampleModel
*/
public boolean isCompatibleSampleModel(SampleModel sm) {
if (! (sm instanceof SinglePixelPackedSampleModel)) {
return false;
}
// Must have the same number of components
if (numComponents != sm.getNumBands()) {
return false;
}
// Transfer type must be the same
if (sm.getTransferType() != transferType) {
return false;
}
SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm;
// Now compare the specific masks
int[] bitMasks = sppsm.getBitMasks();
if (bitMasks.length != maskArray.length) {
return false;
}
/* compare 'effective' masks only, i.e. only part of the mask
* which fits the capacity of the transfer type.
*/
int maxMask = (int)((1L << DataBuffer.getDataTypeSize(transferType)) - 1);
for (int i=0; i < bitMasks.length; i++) {
if ((maxMask & bitMasks[i]) != (maxMask & maskArray[i])) {
return false;
}
}
return true;
}
/**
* Returns a {@link WritableRaster} representing the alpha channel of
* an image, extracted from the input <code>WritableRaster</code>.
* This method assumes that <code>WritableRaster</code> objects
* associated with this <code>ColorModel</code> store the alpha band,
* if present, as the last band of image data. Returns <code>null</code>
* if there is no separate spatial alpha channel associated with this
* <code>ColorModel</code>. This method creates a new
* <code>WritableRaster</code>, but shares the data array.
* @param raster a <code>WritableRaster</code> containing an image
* @return a <code>WritableRaster</code> that represents the alpha
* channel of the image contained in <code>raster</code>.
*/
public WritableRaster getAlphaRaster(WritableRaster raster) {
if (hasAlpha() == false) {
return null;
}
int x = raster.getMinX();
int y = raster.getMinY();
int[] band = new int[1];
band[0] = raster.getNumBands() - 1;
return raster.createWritableChild(x, y, raster.getWidth(),
raster.getHeight(), x, y,
band);
}
/**
* Tests if the specified <code>Object</code> is an instance
* of <code>PackedColorModel</code> and equals this
* <code>PackedColorModel</code>.
* @param obj the <code>Object</code> to test for equality
* @return <code>true</code> if the specified <code>Object</code>
* is an instance of <code>PackedColorModel</code> and equals this
* <code>PackedColorModel</code>; <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
if (!(obj instanceof PackedColorModel)) {
return false;
}
if (!super.equals(obj)) {
return false;
}
PackedColorModel cm = (PackedColorModel) obj;
int numC = cm.getNumComponents();
if (numC != numComponents) {
return false;
}
for(int i=0; i < numC; i++) {
if (maskArray[i] != cm.getMask(i)) {
return false;
}
}
return true;
}
private final static int[] createBitsArray(int[]colorMaskArray,
int alphaMask) {
int numColors = colorMaskArray.length;
int numAlpha = (alphaMask == 0 ? 0 : 1);
int[] arr = new int[numColors+numAlpha];
for (int i=0; i < numColors; i++) {
arr[i] = countBits(colorMaskArray[i]);
if (arr[i] < 0) {
throw new IllegalArgumentException("Noncontiguous color mask ("
+ Integer.toHexString(colorMaskArray[i])+
"at index "+i);
}
}
if (alphaMask != 0) {
arr[numColors] = countBits(alphaMask);
if (arr[numColors] < 0) {
throw new IllegalArgumentException("Noncontiguous alpha mask ("
+ Integer.toHexString(alphaMask));
}
}
return arr;
}
private final static int[] createBitsArray(int rmask, int gmask, int bmask,
int amask) {
int[] arr = new int[3 + (amask == 0 ? 0 : 1)];
arr[0] = countBits(rmask);
arr[1] = countBits(gmask);
arr[2] = countBits(bmask);
if (arr[0] < 0) {
throw new IllegalArgumentException("Noncontiguous red mask ("
+ Integer.toHexString(rmask));
}
else if (arr[1] < 0) {
throw new IllegalArgumentException("Noncontiguous green mask ("
+ Integer.toHexString(gmask));
}
else if (arr[2] < 0) {
throw new IllegalArgumentException("Noncontiguous blue mask ("
+ Integer.toHexString(bmask));
}
if (amask != 0) {
arr[3] = countBits(amask);
if (arr[3] < 0) {
throw new IllegalArgumentException("Noncontiguous alpha mask ("
+ Integer.toHexString(amask));
}
}
return arr;
}
private final static int countBits(int mask) {
int count = 0;
if (mask != 0) {
while ((mask & 1) == 0) {
mask >>>= 1;
}
while ((mask & 1) == 1) {
mask >>>= 1;
count++;
}
}
if (mask != 0) {
return -1;
}
return count;
}
}

View File

@@ -0,0 +1,672 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.util.Hashtable;
import java.awt.image.ImageProducer;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
import java.awt.Image;
/**
* The PixelGrabber class implements an ImageConsumer which can be attached
* to an Image or ImageProducer object to retrieve a subset of the pixels
* in that image. Here is an example:
* <pre>{@code
*
* public void handlesinglepixel(int x, int y, int pixel) {
* int alpha = (pixel >> 24) & 0xff;
* int red = (pixel >> 16) & 0xff;
* int green = (pixel >> 8) & 0xff;
* int blue = (pixel ) & 0xff;
* // Deal with the pixel as necessary...
* }
*
* public void handlepixels(Image img, int x, int y, int w, int h) {
* int[] pixels = new int[w * h];
* PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
* try {
* pg.grabPixels();
* } catch (InterruptedException e) {
* System.err.println("interrupted waiting for pixels!");
* return;
* }
* if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
* System.err.println("image fetch aborted or errored");
* return;
* }
* for (int j = 0; j < h; j++) {
* for (int i = 0; i < w; i++) {
* handlesinglepixel(x+i, y+j, pixels[j * w + i]);
* }
* }
* }
*
* }</pre>
*
* @see ColorModel#getRGBdefault
*
* @author Jim Graham
*/
public class PixelGrabber implements ImageConsumer {
ImageProducer producer;
int dstX;
int dstY;
int dstW;
int dstH;
ColorModel imageModel;
byte[] bytePixels;
int[] intPixels;
int dstOff;
int dstScan;
private boolean grabbing;
private int flags;
private static final int GRABBEDBITS = (ImageObserver.FRAMEBITS
| ImageObserver.ALLBITS);
private static final int DONEBITS = (GRABBEDBITS
| ImageObserver.ERROR);
/**
* Create a PixelGrabber object to grab the (x, y, w, h) rectangular
* section of pixels from the specified image into the given array.
* The pixels are stored into the array in the default RGB ColorModel.
* The RGB data for pixel (i, j) where (i, j) is inside the rectangle
* (x, y, w, h) is stored in the array at
* <tt>pix[(j - y) * scansize + (i - x) + off]</tt>.
* @see ColorModel#getRGBdefault
* @param img the image to retrieve pixels from
* @param x the x coordinate of the upper left corner of the rectangle
* of pixels to retrieve from the image, relative to the default
* (unscaled) size of the image
* @param y the y coordinate of the upper left corner of the rectangle
* of pixels to retrieve from the image
* @param w the width of the rectangle of pixels to retrieve
* @param h the height of the rectangle of pixels to retrieve
* @param pix the array of integers which are to be used to hold the
* RGB pixels retrieved from the image
* @param off the offset into the array of where to store the first pixel
* @param scansize the distance from one row of pixels to the next in
* the array
*/
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);
}
/**
* Create a PixelGrabber object to grab the (x, y, w, h) rectangular
* section of pixels from the image produced by the specified
* ImageProducer into the given array.
* The pixels are stored into the array in the default RGB ColorModel.
* The RGB data for pixel (i, j) where (i, j) is inside the rectangle
* (x, y, w, h) is stored in the array at
* <tt>pix[(j - y) * scansize + (i - x) + off]</tt>.
* @param ip the <code>ImageProducer</code> that produces the
* image from which to retrieve pixels
* @param x the x coordinate of the upper left corner of the rectangle
* of pixels to retrieve from the image, relative to the default
* (unscaled) size of the image
* @param y the y coordinate of the upper left corner of the rectangle
* of pixels to retrieve from the image
* @param w the width of the rectangle of pixels to retrieve
* @param h the height of the rectangle of pixels to retrieve
* @param pix the array of integers which are to be used to hold the
* RGB pixels retrieved from the image
* @param off the offset into the array of where to store the first pixel
* @param scansize the distance from one row of pixels to the next in
* the array
* @see ColorModel#getRGBdefault
*/
public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
int[] pix, int off, int scansize) {
producer = ip;
dstX = x;
dstY = y;
dstW = w;
dstH = h;
dstOff = off;
dstScan = scansize;
intPixels = pix;
imageModel = ColorModel.getRGBdefault();
}
/**
* Create a PixelGrabber object to grab the (x, y, w, h) rectangular
* section of pixels from the specified image. The pixels are
* accumulated in the original ColorModel if the same ColorModel
* is used for every call to setPixels, otherwise the pixels are
* accumulated in the default RGB ColorModel. If the forceRGB
* parameter is true, then the pixels will be accumulated in the
* default RGB ColorModel anyway. A buffer is allocated by the
* PixelGrabber to hold the pixels in either case. If {@code (w < 0)} or
* {@code (h < 0)}, then they will default to the remaining width and
* height of the source data when that information is delivered.
* @param img the image to retrieve the image data from
* @param x the x coordinate of the upper left corner of the rectangle
* of pixels to retrieve from the image, relative to the default
* (unscaled) size of the image
* @param y the y coordinate of the upper left corner of the rectangle
* of pixels to retrieve from the image
* @param w the width of the rectangle of pixels to retrieve
* @param h the height of the rectangle of pixels to retrieve
* @param forceRGB true if the pixels should always be converted to
* the default RGB ColorModel
*/
public PixelGrabber(Image img, int x, int y, int w, int h,
boolean forceRGB)
{
producer = img.getSource();
dstX = x;
dstY = y;
dstW = w;
dstH = h;
if (forceRGB) {
imageModel = ColorModel.getRGBdefault();
}
}
/**
* Request the PixelGrabber to start fetching the pixels.
*/
public synchronized void startGrabbing() {
if ((flags & DONEBITS) != 0) {
return;
}
if (!grabbing) {
grabbing = true;
flags &= ~(ImageObserver.ABORT);
producer.startProduction(this);
}
}
/**
* Request the PixelGrabber to abort the image fetch.
*/
public synchronized void abortGrabbing() {
imageComplete(IMAGEABORTED);
}
/**
* Request the Image or ImageProducer to start delivering pixels and
* wait for all of the pixels in the rectangle of interest to be
* delivered.
* @return true if the pixels were successfully grabbed, false on
* abort, error or timeout
* @exception InterruptedException
* Another thread has interrupted this thread.
*/
public boolean grabPixels() throws InterruptedException {
return grabPixels(0);
}
/**
* Request the Image or ImageProducer to start delivering pixels and
* wait for all of the pixels in the rectangle of interest to be
* delivered or until the specified timeout has elapsed. This method
* behaves in the following ways, depending on the value of
* <code>ms</code>:
* <ul>
* <li> If {@code ms == 0}, waits until all pixels are delivered
* <li> If {@code ms > 0}, waits until all pixels are delivered
* as timeout expires.
* <li> If {@code ms < 0}, returns <code>true</code> if all pixels
* are grabbed, <code>false</code> otherwise and does not wait.
* </ul>
* @param ms the number of milliseconds to wait for the image pixels
* to arrive before timing out
* @return true if the pixels were successfully grabbed, false on
* abort, error or timeout
* @exception InterruptedException
* Another thread has interrupted this thread.
*/
public synchronized boolean grabPixels(long ms)
throws InterruptedException
{
if ((flags & DONEBITS) != 0) {
return (flags & GRABBEDBITS) != 0;
}
long end = ms + System.currentTimeMillis();
if (!grabbing) {
grabbing = true;
flags &= ~(ImageObserver.ABORT);
producer.startProduction(this);
}
while (grabbing) {
long timeout;
if (ms == 0) {
timeout = 0;
} else {
timeout = end - System.currentTimeMillis();
if (timeout <= 0) {
break;
}
}
wait(timeout);
}
return (flags & GRABBEDBITS) != 0;
}
/**
* Return the status of the pixels. The ImageObserver flags
* representing the available pixel information are returned.
* @return the bitwise OR of all relevant ImageObserver flags
* @see ImageObserver
*/
public synchronized int getStatus() {
return flags;
}
/**
* Get the width of the pixel buffer (after adjusting for image width).
* If no width was specified for the rectangle of pixels to grab then
* then this information will only be available after the image has
* delivered the dimensions.
* @return the final width used for the pixel buffer or -1 if the width
* is not yet known
* @see #getStatus
*/
public synchronized int getWidth() {
return (dstW < 0) ? -1 : dstW;
}
/**
* Get the height of the pixel buffer (after adjusting for image height).
* If no width was specified for the rectangle of pixels to grab then
* then this information will only be available after the image has
* delivered the dimensions.
* @return the final height used for the pixel buffer or -1 if the height
* is not yet known
* @see #getStatus
*/
public synchronized int getHeight() {
return (dstH < 0) ? -1 : dstH;
}
/**
* Get the pixel buffer. If the PixelGrabber was not constructed
* with an explicit pixel buffer to hold the pixels then this method
* will return null until the size and format of the image data is
* known.
* Since the PixelGrabber may fall back on accumulating the data
* in the default RGB ColorModel at any time if the source image
* uses more than one ColorModel to deliver the data, the array
* object returned by this method may change over time until the
* image grab is complete.
* @return either a byte array or an int array
* @see #getStatus
* @see #setPixels(int, int, int, int, ColorModel, byte[], int, int)
* @see #setPixels(int, int, int, int, ColorModel, int[], int, int)
*/
public synchronized Object getPixels() {
return (bytePixels == null)
? ((Object) intPixels)
: ((Object) bytePixels);
}
/**
* Get the ColorModel for the pixels stored in the array. If the
* PixelGrabber was constructed with an explicit pixel buffer then
* this method will always return the default RGB ColorModel,
* otherwise it may return null until the ColorModel used by the
* ImageProducer is known.
* Since the PixelGrabber may fall back on accumulating the data
* in the default RGB ColorModel at any time if the source image
* uses more than one ColorModel to deliver the data, the ColorModel
* object returned by this method may change over time until the
* image grab is complete and may not reflect any of the ColorModel
* objects that was used by the ImageProducer to deliver the pixels.
* @return the ColorModel object used for storing the pixels
* @see #getStatus
* @see ColorModel#getRGBdefault
* @see #setColorModel(ColorModel)
*/
public synchronized ColorModel getColorModel() {
return imageModel;
}
/**
* The setDimensions method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param width the width of the dimension
* @param height the height of the dimension
*/
public void setDimensions(int width, int height) {
if (dstW < 0) {
dstW = width - dstX;
}
if (dstH < 0) {
dstH = height - dstY;
}
if (dstW <= 0 || dstH <= 0) {
imageComplete(STATICIMAGEDONE);
} else if (intPixels == null &&
imageModel == ColorModel.getRGBdefault()) {
intPixels = new int[dstW * dstH];
dstScan = dstW;
dstOff = 0;
}
flags |= (ImageObserver.WIDTH | ImageObserver.HEIGHT);
}
/**
* The setHints method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param hints a set of hints used to process the pixels
*/
public void setHints(int hints) {
return;
}
/**
* The setProperties method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param props the list of properties
*/
public void setProperties(Hashtable<?,?> props) {
return;
}
/**
* The setColorModel method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param model the specified <code>ColorModel</code>
* @see #getColorModel
*/
public void setColorModel(ColorModel model) {
return;
}
private void convertToRGB() {
int size = dstW * dstH;
int newpixels[] = new int[size];
if (bytePixels != null) {
for (int i = 0; i < size; i++) {
newpixels[i] = imageModel.getRGB(bytePixels[i] & 0xff);
}
} else if (intPixels != null) {
for (int i = 0; i < size; i++) {
newpixels[i] = imageModel.getRGB(intPixels[i]);
}
}
bytePixels = null;
intPixels = newpixels;
dstScan = dstW;
dstOff = 0;
imageModel = ColorModel.getRGBdefault();
}
/**
* The setPixels method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param srcX the X coordinate of the upper-left corner
* of the area of pixels to be set
* @param srcY the Y coordinate of the upper-left corner
* of the area of pixels to be set
* @param srcW the width of the area of pixels
* @param srcH the height of the area of pixels
* @param model the specified <code>ColorModel</code>
* @param pixels the array of pixels
* @param srcOff the offset into the pixels array
* @param srcScan the distance from one row of pixels to the next
* in the pixels array
* @see #getPixels
*/
public void setPixels(int srcX, int srcY, int srcW, int srcH,
ColorModel model,
byte pixels[], int srcOff, int srcScan) {
if (srcY < dstY) {
int diff = dstY - srcY;
if (diff >= srcH) {
return;
}
srcOff += srcScan * diff;
srcY += diff;
srcH -= diff;
}
if (srcY + srcH > dstY + dstH) {
srcH = (dstY + dstH) - srcY;
if (srcH <= 0) {
return;
}
}
if (srcX < dstX) {
int diff = dstX - srcX;
if (diff >= srcW) {
return;
}
srcOff += diff;
srcX += diff;
srcW -= diff;
}
if (srcX + srcW > dstX + dstW) {
srcW = (dstX + dstW) - srcX;
if (srcW <= 0) {
return;
}
}
int dstPtr = dstOff + (srcY - dstY) * dstScan + (srcX - dstX);
if (intPixels == null) {
if (bytePixels == null) {
bytePixels = new byte[dstW * dstH];
dstScan = dstW;
dstOff = 0;
imageModel = model;
} else if (imageModel != model) {
convertToRGB();
}
if (bytePixels != null) {
for (int h = srcH; h > 0; h--) {
System.arraycopy(pixels, srcOff, bytePixels, dstPtr, srcW);
srcOff += srcScan;
dstPtr += dstScan;
}
}
}
if (intPixels != null) {
int dstRem = dstScan - srcW;
int srcRem = srcScan - srcW;
for (int h = srcH; h > 0; h--) {
for (int w = srcW; w > 0; w--) {
intPixels[dstPtr++] = model.getRGB(pixels[srcOff++]&0xff);
}
srcOff += srcRem;
dstPtr += dstRem;
}
}
flags |= ImageObserver.SOMEBITS;
}
/**
* The setPixels method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param srcX the X coordinate of the upper-left corner
* of the area of pixels to be set
* @param srcY the Y coordinate of the upper-left corner
* of the area of pixels to be set
* @param srcW the width of the area of pixels
* @param srcH the height of the area of pixels
* @param model the specified <code>ColorModel</code>
* @param pixels the array of pixels
* @param srcOff the offset into the pixels array
* @param srcScan the distance from one row of pixels to the next
* in the pixels array
* @see #getPixels
*/
public void setPixels(int srcX, int srcY, int srcW, int srcH,
ColorModel model,
int pixels[], int srcOff, int srcScan) {
if (srcY < dstY) {
int diff = dstY - srcY;
if (diff >= srcH) {
return;
}
srcOff += srcScan * diff;
srcY += diff;
srcH -= diff;
}
if (srcY + srcH > dstY + dstH) {
srcH = (dstY + dstH) - srcY;
if (srcH <= 0) {
return;
}
}
if (srcX < dstX) {
int diff = dstX - srcX;
if (diff >= srcW) {
return;
}
srcOff += diff;
srcX += diff;
srcW -= diff;
}
if (srcX + srcW > dstX + dstW) {
srcW = (dstX + dstW) - srcX;
if (srcW <= 0) {
return;
}
}
if (intPixels == null) {
if (bytePixels == null) {
intPixels = new int[dstW * dstH];
dstScan = dstW;
dstOff = 0;
imageModel = model;
} else {
convertToRGB();
}
}
int dstPtr = dstOff + (srcY - dstY) * dstScan + (srcX - dstX);
if (imageModel == model) {
for (int h = srcH; h > 0; h--) {
System.arraycopy(pixels, srcOff, intPixels, dstPtr, srcW);
srcOff += srcScan;
dstPtr += dstScan;
}
} else {
if (imageModel != ColorModel.getRGBdefault()) {
convertToRGB();
}
int dstRem = dstScan - srcW;
int srcRem = srcScan - srcW;
for (int h = srcH; h > 0; h--) {
for (int w = srcW; w > 0; w--) {
intPixels[dstPtr++] = model.getRGB(pixels[srcOff++]);
}
srcOff += srcRem;
dstPtr += dstRem;
}
}
flags |= ImageObserver.SOMEBITS;
}
/**
* The imageComplete method is part of the ImageConsumer API which
* this class must implement to retrieve the pixels.
* <p>
* Note: This method is intended to be called by the ImageProducer
* of the Image whose pixels are being grabbed. Developers using
* this class to retrieve pixels from an image should avoid calling
* this method directly since that operation could result in problems
* with retrieving the requested pixels.
* @param status the status of image loading
*/
public synchronized void imageComplete(int status) {
grabbing = false;
switch (status) {
default:
case IMAGEERROR:
flags |= ImageObserver.ERROR | ImageObserver.ABORT;
break;
case IMAGEABORTED:
flags |= ImageObserver.ABORT;
break;
case STATICIMAGEDONE:
flags |= ImageObserver.ALLBITS;
break;
case SINGLEFRAMEDONE:
flags |= ImageObserver.FRAMEBITS;
break;
}
producer.removeConsumer(this);
notifyAll();
}
/**
* Returns the status of the pixels. The ImageObserver flags
* representing the available pixel information are returned.
* This method and {@link #getStatus() getStatus} have the
* same implementation, but <code>getStatus</code> is the
* preferred method because it conforms to the convention of
* naming information-retrieval methods with the form
* "getXXX".
* @return the bitwise OR of all relevant ImageObserver flags
* @see ImageObserver
* @see #getStatus()
*/
public synchronized int status() {
return flags;
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* This class represents image data which is stored in a pixel interleaved
* fashion and for
* which each sample of a pixel occupies one data element of the DataBuffer.
* It subclasses ComponentSampleModel but provides a more efficient
* implementation for accessing pixel interleaved image data than is provided
* by ComponentSampleModel. This class
* stores sample data for all bands in a single bank of the
* DataBuffer. Accessor methods are provided so that image data can be
* manipulated directly. Pixel stride is the number of
* data array elements between two samples for the same band on the same
* scanline. Scanline stride is the number of data array elements between
* a given sample and the corresponding sample in the same column of the next
* scanline. Band offsets denote the number
* of data array elements from the first data array element of the bank
* of the DataBuffer holding each band to the first sample of the band.
* The bands are numbered from 0 to N-1.
* Bank indices denote the correspondence between a bank of the data buffer
* and a band of image data.
* This class supports
* {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
* {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
* {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
* {@link DataBuffer#TYPE_INT TYPE_INT},
* {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT} and
* {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes.
*/
public class PixelInterleavedSampleModel extends ComponentSampleModel
{
/**
* Constructs a PixelInterleavedSampleModel with the specified parameters.
* The number of bands will be given by the length of the bandOffsets
* array.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param pixelStride The pixel stride of the image data.
* @param scanlineStride The line stride of the image data.
* @param bandOffsets The offsets of all bands.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
* @throws IllegalArgumentException if any offset between bands is
* greater than the scanline stride
* @throws IllegalArgumentException if the product of
* <code>pixelStride</code> and <code>w</code> is greater
* than <code>scanlineStride</code>
* @throws IllegalArgumentException if <code>pixelStride</code> is
* less than any offset between bands
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public PixelInterleavedSampleModel(int dataType,
int w, int h,
int pixelStride,
int scanlineStride,
int bandOffsets[]) {
super(dataType, w, h, pixelStride, scanlineStride, bandOffsets);
int minBandOff=this.bandOffsets[0];
int maxBandOff=this.bandOffsets[0];
for (int i=1; i<this.bandOffsets.length; i++) {
minBandOff = Math.min(minBandOff,this.bandOffsets[i]);
maxBandOff = Math.max(maxBandOff,this.bandOffsets[i]);
}
maxBandOff -= minBandOff;
if (maxBandOff > scanlineStride) {
throw new IllegalArgumentException("Offsets between bands must be"+
" less than the scanline "+
" stride");
}
if (pixelStride*w > scanlineStride) {
throw new IllegalArgumentException("Pixel stride times width "+
"must be less than or "+
"equal to the scanline "+
"stride");
}
if (pixelStride < maxBandOff) {
throw new IllegalArgumentException("Pixel stride must be greater"+
" than or equal to the offsets"+
" between bands");
}
}
/**
* Creates a new PixelInterleavedSampleModel with the specified
* width and height. The new PixelInterleavedSampleModel will have the
* same number of bands, storage data type, and pixel stride
* as this PixelInterleavedSampleModel. The band offsets may be
* compressed such that the minimum of all of the band offsets is zero.
* @param w the width of the resulting <code>SampleModel</code>
* @param h the height of the resulting <code>SampleModel</code>
* @return a new <code>SampleModel</code> with the specified width
* and height.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
int minBandoff=bandOffsets[0];
int numBands = bandOffsets.length;
for (int i=1; i < numBands; i++) {
if (bandOffsets[i] < minBandoff) {
minBandoff = bandOffsets[i];
}
}
int[] bandOff;
if (minBandoff > 0) {
bandOff = new int[numBands];
for (int i=0; i < numBands; i++) {
bandOff[i] = bandOffsets[i] - minBandoff;
}
}
else {
bandOff = bandOffsets;
}
return new PixelInterleavedSampleModel(dataType, w, h, pixelStride,
pixelStride*w, bandOff);
}
/**
* Creates a new PixelInterleavedSampleModel with a subset of the
* bands of this PixelInterleavedSampleModel. The new
* PixelInterleavedSampleModel can be used with any DataBuffer that the
* existing PixelInterleavedSampleModel can be used with. The new
* PixelInterleavedSampleModel/DataBuffer combination will represent
* an image with a subset of the bands of the original
* PixelInterleavedSampleModel/DataBuffer combination.
*/
public SampleModel createSubsetSampleModel(int bands[]) {
int newBandOffsets[] = new int[bands.length];
for (int i=0; i<bands.length; i++) {
newBandOffsets[i] = bandOffsets[bands[i]];
}
return new PixelInterleavedSampleModel(this.dataType, width, height,
this.pixelStride,
scanlineStride, newBandOffsets);
}
// Differentiate hash code from other ComponentSampleModel subclasses
public int hashCode() {
return super.hashCode() ^ 0x1;
}
}

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
/**
* This class provides an easy way to create an ImageFilter which modifies
* the pixels of an image in the default RGB ColorModel. It is meant to
* be used in conjunction with a FilteredImageSource object to produce
* filtered versions of existing images. It is an abstract class that
* provides the calls needed to channel all of the pixel data through a
* single method which converts pixels one at a time in the default RGB
* ColorModel regardless of the ColorModel being used by the ImageProducer.
* The only method which needs to be defined to create a useable image
* filter is the filterRGB method. Here is an example of a definition
* of a filter which swaps the red and blue components of an image:
* <pre>{@code
*
* class RedBlueSwapFilter extends RGBImageFilter {
* public RedBlueSwapFilter() {
* // The filter's operation does not depend on the
* // pixel's location, so IndexColorModels can be
* // filtered directly.
* canFilterIndexColorModel = true;
* }
*
* public int filterRGB(int x, int y, int rgb) {
* return ((rgb & 0xff00ff00)
* | ((rgb & 0xff0000) >> 16)
* | ((rgb & 0xff) << 16));
* }
* }
*
* }</pre>
*
* @see FilteredImageSource
* @see ImageFilter
* @see ColorModel#getRGBdefault
*
* @author Jim Graham
*/
public abstract class RGBImageFilter extends ImageFilter {
/**
* The <code>ColorModel</code> to be replaced by
* <code>newmodel</code> when the user calls
* {@link #substituteColorModel(ColorModel, ColorModel) substituteColorModel}.
*/
protected ColorModel origmodel;
/**
* The <code>ColorModel</code> with which to
* replace <code>origmodel</code> when the user calls
* <code>substituteColorModel</code>.
*/
protected ColorModel newmodel;
/**
* This boolean indicates whether or not it is acceptable to apply
* the color filtering of the filterRGB method to the color table
* entries of an IndexColorModel object in lieu of pixel by pixel
* filtering. Subclasses should set this variable to true in their
* constructor if their filterRGB method does not depend on the
* coordinate of the pixel being filtered.
* @see #substituteColorModel
* @see #filterRGB
* @see IndexColorModel
*/
protected boolean canFilterIndexColorModel;
/**
* If the ColorModel is an IndexColorModel and the subclass has
* set the canFilterIndexColorModel flag to true, we substitute
* a filtered version of the color model here and wherever
* that original ColorModel object appears in the setPixels methods.
* If the ColorModel is not an IndexColorModel or is null, this method
* overrides the default ColorModel used by the ImageProducer and
* specifies the default RGB ColorModel instead.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer
* @see ColorModel#getRGBdefault
*/
public void setColorModel(ColorModel model) {
if (canFilterIndexColorModel && (model instanceof IndexColorModel)) {
ColorModel newcm = filterIndexColorModel((IndexColorModel)model);
substituteColorModel(model, newcm);
consumer.setColorModel(newcm);
} else {
consumer.setColorModel(ColorModel.getRGBdefault());
}
}
/**
* Registers two ColorModel objects for substitution. If the oldcm
* is encountered during any of the setPixels methods, the newcm
* is substituted and the pixels passed through
* untouched (but with the new ColorModel object).
* @param oldcm the ColorModel object to be replaced on the fly
* @param newcm the ColorModel object to replace oldcm on the fly
*/
public void substituteColorModel(ColorModel oldcm, ColorModel newcm) {
origmodel = oldcm;
newmodel = newcm;
}
/**
* Filters an IndexColorModel object by running each entry in its
* color tables through the filterRGB function that RGBImageFilter
* subclasses must provide. Uses coordinates of -1 to indicate that
* a color table entry is being filtered rather than an actual
* pixel value.
* @param icm the IndexColorModel object to be filtered
* @exception NullPointerException if <code>icm</code> is null
* @return a new IndexColorModel representing the filtered colors
*/
public IndexColorModel filterIndexColorModel(IndexColorModel icm) {
int mapsize = icm.getMapSize();
byte r[] = new byte[mapsize];
byte g[] = new byte[mapsize];
byte b[] = new byte[mapsize];
byte a[] = new byte[mapsize];
icm.getReds(r);
icm.getGreens(g);
icm.getBlues(b);
icm.getAlphas(a);
int trans = icm.getTransparentPixel();
boolean needalpha = false;
for (int i = 0; i < mapsize; i++) {
int rgb = filterRGB(-1, -1, icm.getRGB(i));
a[i] = (byte) (rgb >> 24);
if (a[i] != ((byte)0xff) && i != trans) {
needalpha = true;
}
r[i] = (byte) (rgb >> 16);
g[i] = (byte) (rgb >> 8);
b[i] = (byte) (rgb >> 0);
}
if (needalpha) {
return new IndexColorModel(icm.getPixelSize(), mapsize,
r, g, b, a);
} else {
return new IndexColorModel(icm.getPixelSize(), mapsize,
r, g, b, trans);
}
}
/**
* Filters a buffer of pixels in the default RGB ColorModel by passing
* them one by one through the filterRGB method.
* @param x the X coordinate of the upper-left corner of the region
* of pixels
* @param y the Y coordinate of the upper-left corner of the region
* of pixels
* @param w the width of the region of pixels
* @param h the height of the region of pixels
* @param pixels the array of pixels
* @param off the offset into the <code>pixels</code> array
* @param scansize the distance from one row of pixels to the next
* in the array
* @see ColorModel#getRGBdefault
* @see #filterRGB
*/
public void filterRGBPixels(int x, int y, int w, int h,
int pixels[], int off, int scansize) {
int index = off;
for (int cy = 0; cy < h; cy++) {
for (int cx = 0; cx < w; cx++) {
pixels[index] = filterRGB(x + cx, y + cy, pixels[index]);
index++;
}
index += scansize - w;
}
consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(),
pixels, off, scansize);
}
/**
* If the ColorModel object is the same one that has already
* been converted, then simply passes the pixels through with the
* converted ColorModel. Otherwise converts the buffer of byte
* pixels to the default RGB ColorModel and passes the converted
* buffer to the filterRGBPixels method to be converted one by one.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ColorModel#getRGBdefault
* @see #filterRGBPixels
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off,
int scansize) {
if (model == origmodel) {
consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
} else {
int filteredpixels[] = new int[w];
int index = off;
for (int cy = 0; cy < h; cy++) {
for (int cx = 0; cx < w; cx++) {
filteredpixels[cx] = model.getRGB((pixels[index] & 0xff));
index++;
}
index += scansize - w;
filterRGBPixels(x, y + cy, w, 1, filteredpixels, 0, w);
}
}
}
/**
* If the ColorModel object is the same one that has already
* been converted, then simply passes the pixels through with the
* converted ColorModel, otherwise converts the buffer of integer
* pixels to the default RGB ColorModel and passes the converted
* buffer to the filterRGBPixels method to be converted one by one.
* Converts a buffer of integer pixels to the default RGB ColorModel
* and passes the converted buffer to the filterRGBPixels method.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ColorModel#getRGBdefault
* @see #filterRGBPixels
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off,
int scansize) {
if (model == origmodel) {
consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
} else {
int filteredpixels[] = new int[w];
int index = off;
for (int cy = 0; cy < h; cy++) {
for (int cx = 0; cx < w; cx++) {
filteredpixels[cx] = model.getRGB(pixels[index]);
index++;
}
index += scansize - w;
filterRGBPixels(x, y + cy, w, 1, filteredpixels, 0, w);
}
}
}
/**
* Subclasses must specify a method to convert a single input pixel
* in the default RGB ColorModel to a single output pixel.
* @param x the X coordinate of the pixel
* @param y the Y coordinate of the pixel
* @param rgb the integer pixel representation in the default RGB
* color model
* @return a filtered pixel in the default RGB color model.
* @see ColorModel#getRGBdefault
* @see #filterRGBPixels
*/
public abstract int filterRGB(int x, int y, int rgb);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* The <code>RasterFormatException</code> is thrown if there is
* invalid layout information in the {@link Raster}.
*/
public class RasterFormatException extends java.lang.RuntimeException {
/**
* Constructs a new <code>RasterFormatException</code> with the
* specified message.
* @param s the message to generate when a
* <code>RasterFormatException</code> is thrown
*/
public RasterFormatException(String s) {
super (s);
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Point2D;
import java.awt.RenderingHints;
/**
* This interface describes single-input/single-output
* operations performed on Raster objects. It is implemented by such
* classes as AffineTransformOp, ConvolveOp, and LookupOp. The Source
* and Destination objects must contain the appropriate number
* of bands for the particular classes implementing this interface.
* Otherwise, an exception is thrown. This interface cannot be used to
* describe more sophisticated Ops such as ones that take multiple sources.
* Each class implementing this interface will specify whether or not it
* will allow an in-place filtering operation (i.e. source object equal
* to the destination object). Note that the restriction to single-input
* operations means that the values of destination pixels prior to the
* operation are not used as input to the filter operation.
* @see AffineTransformOp
* @see BandCombineOp
* @see ColorConvertOp
* @see ConvolveOp
* @see LookupOp
* @see RescaleOp
*/
public interface RasterOp {
/**
* Performs a single-input/single-output operation from a source Raster
* to a destination Raster. If the destination Raster is null, a
* new Raster will be created. The IllegalArgumentException may be thrown
* if the source and/or destination Raster is incompatible with the types
* of Rasters allowed by the class implementing this filter.
* @param src the source <code>Raster</code>
* @param dest the destination <code>WritableRaster</code>
* @return a <code>WritableRaster</code> that represents the result of
* the filtering operation.
*/
public WritableRaster filter(Raster src, WritableRaster dest);
/**
* Returns the bounding box of the filtered destination Raster.
* The IllegalArgumentException may be thrown if the source Raster
* is incompatible with the types of Rasters allowed
* by the class implementing this filter.
* @param src the source <code>Raster</code>
* @return a <code>Rectangle2D</code> that is the bounding box of
* the <code>Raster</code> resulting from the filtering
* operation.
*/
public Rectangle2D getBounds2D(Raster src);
/**
* Creates a zeroed destination Raster with the correct size and number of
* bands.
* The IllegalArgumentException may be thrown if the source Raster
* is incompatible with the types of Rasters allowed
* by the class implementing this filter.
* @param src the source <code>Raster</code>
* @return a <code>WritableRaster</code> that is compatible with
* <code>src</code>
*/
public WritableRaster createCompatibleDestRaster(Raster src);
/**
* Returns the location of the destination point given a
* point in the source Raster. If dstPt is non-null, it
* will be used to hold the return value.
* @param srcPt the source <code>Point2D</code>
* @param dstPt the destination <code>Point2D</code>
* @return the location of the destination point.
*/
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt);
/**
* Returns the rendering hints for this RasterOp. Returns
* null if no hints have been set.
* @return the <code>RenderingHints</code> object of this
* <code>RasterOp</code>.
*/
public RenderingHints getRenderingHints();
}

View File

@@ -0,0 +1,217 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.awt.Rectangle;
import java.util.Dictionary;
import java.util.Vector;
/**
* RenderedImage is a common interface for objects which contain
* or can produce image data in the form of Rasters. The image
* data may be stored/produced as a single tile or a regular array
* of tiles.
*/
public interface RenderedImage {
/**
* Returns a vector of RenderedImages that are the immediate sources of
* image data for this RenderedImage. This method returns null if
* the RenderedImage object has no information about its immediate
* sources. It returns an empty Vector if the RenderedImage object has
* no immediate sources.
* @return a Vector of <code>RenderedImage</code> objects.
*/
Vector<RenderedImage> getSources();
/**
* Gets a property from the property set of this image. The set of
* properties and whether it is immutable is determined by the
* implementing class. This method returns
* java.awt.Image.UndefinedProperty if the specified property is
* not defined for this RenderedImage.
* @param name the name of the property
* @return the property indicated by the specified name.
* @see java.awt.Image#UndefinedProperty
*/
Object getProperty(String name);
/**
* Returns an array of names recognized by
* {@link #getProperty(String) getProperty(String)}
* or <code>null</code>, if no property names are recognized.
* @return a <code>String</code> array containing all of the
* property names that <code>getProperty(String)</code> recognizes;
* or <code>null</code> if no property names are recognized.
*/
String[] getPropertyNames();
/**
* Returns the ColorModel associated with this image. All Rasters
* returned from this image will have this as their ColorModel. This
* can return null.
* @return the <code>ColorModel</code> of this image.
*/
ColorModel getColorModel();
/**
* Returns the SampleModel associated with this image. All Rasters
* returned from this image will have this as their SampleModel.
* @return the <code>SampleModel</code> of this image.
*/
SampleModel getSampleModel();
/**
* Returns the width of the RenderedImage.
* @return the width of this <code>RenderedImage</code>.
*/
int getWidth();
/**
* Returns the height of the RenderedImage.
* @return the height of this <code>RenderedImage</code>.
*/
int getHeight();
/**
* Returns the minimum X coordinate (inclusive) of the RenderedImage.
* @return the X coordinate of this <code>RenderedImage</code>.
*/
int getMinX();
/**
* Returns the minimum Y coordinate (inclusive) of the RenderedImage.
* @return the Y coordinate of this <code>RenderedImage</code>.
*/
int getMinY();
/**
* Returns the number of tiles in the X direction.
* @return the number of tiles in the X direction.
*/
int getNumXTiles();
/**
* Returns the number of tiles in the Y direction.
* @return the number of tiles in the Y direction.
*/
int getNumYTiles();
/**
* Returns the minimum tile index in the X direction.
* @return the minimum tile index in the X direction.
*/
int getMinTileX();
/**
* Returns the minimum tile index in the Y direction.
* @return the minimum tile index in the X direction.
*/
int getMinTileY();
/**
* Returns the tile width in pixels. All tiles must have the same
* width.
* @return the tile width in pixels.
*/
int getTileWidth();
/**
* Returns the tile height in pixels. All tiles must have the same
* height.
* @return the tile height in pixels.
*/
int getTileHeight();
/**
* Returns the X offset of the tile grid relative to the origin,
* i.e., the X coordinate of the upper-left pixel of tile (0, 0).
* (Note that tile (0, 0) may not actually exist.)
* @return the X offset of the tile grid relative to the origin.
*/
int getTileGridXOffset();
/**
* Returns the Y offset of the tile grid relative to the origin,
* i.e., the Y coordinate of the upper-left pixel of tile (0, 0).
* (Note that tile (0, 0) may not actually exist.)
* @return the Y offset of the tile grid relative to the origin.
*/
int getTileGridYOffset();
/**
* Returns tile (tileX, tileY). Note that tileX and tileY are indices
* into the tile array, not pixel locations. The Raster that is returned
* is live and will be updated if the image is changed.
* @param tileX the X index of the requested tile in the tile array
* @param tileY the Y index of the requested tile in the tile array
* @return the tile given the specified indices.
*/
Raster getTile(int tileX, int tileY);
/**
* Returns the image as one large tile (for tile based
* images this will require fetching the whole image
* and copying the image data over). The Raster returned is
* a copy of the image data and will not be updated if the image
* is changed.
* @return the image as one large tile.
*/
Raster getData();
/**
* Computes and returns an arbitrary region of the RenderedImage.
* The Raster returned is a copy of the image data and will not
* be updated if the image is changed.
* @param rect the region of the RenderedImage to be returned.
* @return the region of the <code>RenderedImage</code>
* indicated by the specified <code>Rectangle</code>.
*/
Raster getData(Rectangle rect);
/**
* Computes an arbitrary rectangular region of the RenderedImage
* and copies it into a caller-supplied WritableRaster. The region
* to be computed is determined from the bounds of the supplied
* WritableRaster. The supplied WritableRaster must have a
* SampleModel that is compatible with this image. If raster is null,
* an appropriate WritableRaster is created.
* @param raster a WritableRaster to hold the returned portion of the
* image, or null.
* @return a reference to the supplied or created WritableRaster.
*/
WritableRaster copyData(WritableRaster raster);
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
import java.util.Hashtable;
import java.awt.Rectangle;
/**
* An ImageFilter class for scaling images using the simplest algorithm.
* This class extends the basic ImageFilter Class to scale an existing
* image and provide a source for a new image containing the resampled
* image. The pixels in the source image are sampled to produce pixels
* for an image of the specified size by replicating rows and columns of
* pixels to scale up or omitting rows and columns of pixels to scale
* down.
* <p>It is meant to be used in conjunction with a FilteredImageSource
* object to produce scaled versions of existing images. Due to
* implementation dependencies, there may be differences in pixel values
* of an image filtered on different platforms.
*
* @see FilteredImageSource
* @see ImageFilter
*
* @author Jim Graham
*/
public class ReplicateScaleFilter extends ImageFilter {
/**
* The width of the source image.
*/
protected int srcWidth;
/**
* The height of the source image.
*/
protected int srcHeight;
/**
* The target width to scale the image.
*/
protected int destWidth;
/**
* The target height to scale the image.
*/
protected int destHeight;
/**
* An <code>int</code> array containing information about a
* row of pixels.
*/
protected int srcrows[];
/**
* An <code>int</code> array containing information about a
* column of pixels.
*/
protected int srccols[];
/**
* A <code>byte</code> array initialized with a size of
* {@link #destWidth} and used to deliver a row of pixel
* data to the {@link ImageConsumer}.
*/
protected Object outpixbuf;
/**
* Constructs a ReplicateScaleFilter that scales the pixels from
* its source Image as specified by the width and height parameters.
* @param width the target width to scale the image
* @param height the target height to scale the image
* @throws IllegalArgumentException if <code>width</code> equals
* zero or <code>height</code> equals zero
*/
public ReplicateScaleFilter(int width, int height) {
if (width == 0 || height == 0) {
throw new IllegalArgumentException("Width ("+width+
") and height ("+height+
") must be non-zero");
}
destWidth = width;
destHeight = height;
}
/**
* Passes along the properties from the source object after adding a
* property indicating the scale applied.
* This method invokes <code>super.setProperties</code>,
* which might result in additional properties being added.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*/
public void setProperties(Hashtable<?,?> props) {
Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
String key = "rescale";
String val = destWidth + "x" + destHeight;
Object o = p.get(key);
if (o != null && o instanceof String) {
val = ((String) o) + ", " + val;
}
p.put(key, val);
super.setProperties(p);
}
/**
* Override the dimensions of the source image and pass the dimensions
* of the new scaled size to the ImageConsumer.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
* @see ImageConsumer
*/
public void setDimensions(int w, int h) {
srcWidth = w;
srcHeight = h;
if (destWidth < 0) {
if (destHeight < 0) {
destWidth = srcWidth;
destHeight = srcHeight;
} else {
destWidth = srcWidth * destHeight / srcHeight;
}
} else if (destHeight < 0) {
destHeight = srcHeight * destWidth / srcWidth;
}
consumer.setDimensions(destWidth, destHeight);
}
private void calculateMaps() {
srcrows = new int[destHeight + 1];
for (int y = 0; y <= destHeight; y++) {
srcrows[y] = (2 * y * srcHeight + srcHeight) / (2 * destHeight);
}
srccols = new int[destWidth + 1];
for (int x = 0; x <= destWidth; x++) {
srccols[x] = (2 * x * srcWidth + srcWidth) / (2 * destWidth);
}
}
/**
* Choose which rows and columns of the delivered byte pixels are
* needed for the destination scaled image and pass through just
* those rows and columns that are needed, replicated as necessary.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte pixels[], int off,
int scansize) {
if (srcrows == null || srccols == null) {
calculateMaps();
}
int sx, sy;
int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth);
int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * srcHeight);
byte outpix[];
if (outpixbuf != null && outpixbuf instanceof byte[]) {
outpix = (byte[]) outpixbuf;
} else {
outpix = new byte[destWidth];
outpixbuf = outpix;
}
for (int dy = dy1; (sy = srcrows[dy]) < y + h; dy++) {
int srcoff = off + scansize * (sy - y);
int dx;
for (dx = dx1; (sx = srccols[dx]) < x + w; dx++) {
outpix[dx] = pixels[srcoff + sx - x];
}
if (dx > dx1) {
consumer.setPixels(dx1, dy, dx - dx1, 1,
model, outpix, dx1, destWidth);
}
}
}
/**
* Choose which rows and columns of the delivered int pixels are
* needed for the destination scaled image and pass through just
* those rows and columns that are needed, replicated as necessary.
* <p>
* Note: This method is intended to be called by the
* <code>ImageProducer</code> of the <code>Image</code> whose pixels
* are being filtered. Developers using
* this class to filter pixels from an image should avoid calling
* this method directly since that operation could interfere
* with the filtering operation.
*/
public void setPixels(int x, int y, int w, int h,
ColorModel model, int pixels[], int off,
int scansize) {
if (srcrows == null || srccols == null) {
calculateMaps();
}
int sx, sy;
int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth);
int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * srcHeight);
int outpix[];
if (outpixbuf != null && outpixbuf instanceof int[]) {
outpix = (int[]) outpixbuf;
} else {
outpix = new int[destWidth];
outpixbuf = outpix;
}
for (int dy = dy1; (sy = srcrows[dy]) < y + h; dy++) {
int srcoff = off + scansize * (sy - y);
int dx;
for (dx = dx1; (sx = srccols[dx]) < x + w; dx++) {
outpix[dx] = pixels[srcoff + sx - x];
}
if (dx > dx1) {
consumer.setPixels(dx1, dy, dx - dx1, 1,
model, outpix, dx1, destWidth);
}
}
}
}

View File

@@ -0,0 +1,692 @@
/*
* Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.color.ColorSpace;
import java.awt.geom.Rectangle2D;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.RenderingHints;
import sun.awt.image.ImagingLib;
/**
* This class performs a pixel-by-pixel rescaling of the data in the
* source image by multiplying the sample values for each pixel by a scale
* factor and then adding an offset. The scaled sample values are clipped
* to the minimum/maximum representable in the destination image.
* <p>
* The pseudo code for the rescaling operation is as follows:
* <pre>
*for each pixel from Source object {
* for each band/component of the pixel {
* dstElement = (srcElement*scaleFactor) + offset
* }
*}
* </pre>
* <p>
* For Rasters, rescaling operates on bands. The number of
* sets of scaling constants may be one, in which case the same constants
* are applied to all bands, or it must equal the number of Source
* Raster bands.
* <p>
* For BufferedImages, rescaling operates on color and alpha components.
* The number of sets of scaling constants may be one, in which case the
* same constants are applied to all color (but not alpha) components.
* Otherwise, the number of sets of scaling constants may
* equal the number of Source color components, in which case no
* rescaling of the alpha component (if present) is performed.
* If neither of these cases apply, the number of sets of scaling constants
* must equal the number of Source color components plus alpha components,
* in which case all color and alpha components are rescaled.
* <p>
* BufferedImage sources with premultiplied alpha data are treated in the same
* manner as non-premultiplied images for purposes of rescaling. That is,
* the rescaling is done per band on the raw data of the BufferedImage source
* without regard to whether the data is premultiplied. If a color conversion
* is required to the destination ColorModel, the premultiplied state of
* both source and destination will be taken into account for this step.
* <p>
* Images with an IndexColorModel cannot be rescaled.
* <p>
* If a RenderingHints object is specified in the constructor, the
* color rendering hint and the dithering hint may be used when color
* conversion is required.
* <p>
* Note that in-place operation is allowed (i.e. the source and destination can
* be the same object).
* @see java.awt.RenderingHints#KEY_COLOR_RENDERING
* @see java.awt.RenderingHints#KEY_DITHERING
*/
public class RescaleOp implements BufferedImageOp, RasterOp {
float[] scaleFactors;
float[] offsets;
int length = 0;
RenderingHints hints;
private int srcNbits;
private int dstNbits;
/**
* Constructs a new RescaleOp with the desired scale factors
* and offsets. The length of the scaleFactor and offset arrays
* must meet the restrictions stated in the class comments above.
* The RenderingHints argument may be null.
* @param scaleFactors the specified scale factors
* @param offsets the specified offsets
* @param hints the specified <code>RenderingHints</code>, or
* <code>null</code>
*/
public RescaleOp (float[] scaleFactors, float[] offsets,
RenderingHints hints) {
length = scaleFactors.length;
if (length > offsets.length) length = offsets.length;
this.scaleFactors = new float[length];
this.offsets = new float[length];
for (int i=0; i < length; i++) {
this.scaleFactors[i] = scaleFactors[i];
this.offsets[i] = offsets[i];
}
this.hints = hints;
}
/**
* Constructs a new RescaleOp with the desired scale factor
* and offset. The scaleFactor and offset will be applied to
* all bands in a source Raster and to all color (but not alpha)
* components in a BufferedImage.
* The RenderingHints argument may be null.
* @param scaleFactor the specified scale factor
* @param offset the specified offset
* @param hints the specified <code>RenderingHints</code>, or
* <code>null</code>
*/
public RescaleOp (float scaleFactor, float offset, RenderingHints hints) {
length = 1;
this.scaleFactors = new float[1];
this.offsets = new float[1];
this.scaleFactors[0] = scaleFactor;
this.offsets[0] = offset;
this.hints = hints;
}
/**
* Returns the scale factors in the given array. The array is also
* returned for convenience. If scaleFactors is null, a new array
* will be allocated.
* @param scaleFactors the array to contain the scale factors of
* this <code>RescaleOp</code>
* @return the scale factors of this <code>RescaleOp</code>.
*/
final public float[] getScaleFactors (float scaleFactors[]) {
if (scaleFactors == null) {
return (float[]) this.scaleFactors.clone();
}
System.arraycopy (this.scaleFactors, 0, scaleFactors, 0,
Math.min(this.scaleFactors.length,
scaleFactors.length));
return scaleFactors;
}
/**
* Returns the offsets in the given array. The array is also returned
* for convenience. If offsets is null, a new array
* will be allocated.
* @param offsets the array to contain the offsets of
* this <code>RescaleOp</code>
* @return the offsets of this <code>RescaleOp</code>.
*/
final public float[] getOffsets(float offsets[]) {
if (offsets == null) {
return (float[]) this.offsets.clone();
}
System.arraycopy (this.offsets, 0, offsets, 0,
Math.min(this.offsets.length, offsets.length));
return offsets;
}
/**
* Returns the number of scaling factors and offsets used in this
* RescaleOp.
* @return the number of scaling factors and offsets of this
* <code>RescaleOp</code>.
*/
final public int getNumFactors() {
return length;
}
/**
* Creates a ByteLookupTable to implement the rescale.
* The table may have either a SHORT or BYTE input.
* @param nElems Number of elements the table is to have.
* This will generally be 256 for byte and
* 65536 for short.
*/
private ByteLookupTable createByteLut(float scale[],
float off[],
int nBands,
int nElems) {
byte[][] lutData = new byte[nBands][nElems];
int band;
for (band=0; band<scale.length; band++) {
float bandScale = scale[band];
float bandOff = off[band];
byte[] bandLutData = lutData[band];
for (int i=0; i<nElems; i++) {
int val = (int)(i*bandScale + bandOff);
if ((val & 0xffffff00) != 0) {
if (val < 0) {
val = 0;
} else {
val = 255;
}
}
bandLutData[i] = (byte)val;
}
}
int maxToCopy = (nBands == 4 && scale.length == 4) ? 4 : 3;
while (band < lutData.length && band < maxToCopy) {
System.arraycopy(lutData[band-1], 0, lutData[band], 0, nElems);
band++;
}
if (nBands == 4 && band < nBands) {
byte[] bandLutData = lutData[band];
for (int i=0; i<nElems; i++) {
bandLutData[i] = (byte)i;
}
}
return new ByteLookupTable(0, lutData);
}
/**
* Creates a ShortLookupTable to implement the rescale.
* The table may have either a SHORT or BYTE input.
* @param nElems Number of elements the table is to have.
* This will generally be 256 for byte and
* 65536 for short.
*/
private ShortLookupTable createShortLut(float scale[],
float off[],
int nBands,
int nElems) {
short[][] lutData = new short[nBands][nElems];
int band = 0;
for (band=0; band<scale.length; band++) {
float bandScale = scale[band];
float bandOff = off[band];
short[] bandLutData = lutData[band];
for (int i=0; i<nElems; i++) {
int val = (int)(i*bandScale + bandOff);
if ((val & 0xffff0000) != 0) {
if (val < 0) {
val = 0;
} else {
val = 65535;
}
}
bandLutData[i] = (short)val;
}
}
int maxToCopy = (nBands == 4 && scale.length == 4) ? 4 : 3;
while (band < lutData.length && band < maxToCopy) {
System.arraycopy(lutData[band-1], 0, lutData[band], 0, nElems);
band++;
}
if (nBands == 4 && band < nBands) {
short[] bandLutData = lutData[band];
for (int i=0; i<nElems; i++) {
bandLutData[i] = (short)i;
}
}
return new ShortLookupTable(0, lutData);
}
/**
* Determines if the rescale can be performed as a lookup.
* The dst must be a byte or short type.
* The src must be less than 16 bits.
* All source band sizes must be the same and all dst band sizes
* must be the same.
*/
private boolean canUseLookup(Raster src, Raster dst) {
//
// Check that the src datatype is either a BYTE or SHORT
//
int datatype = src.getDataBuffer().getDataType();
if(datatype != DataBuffer.TYPE_BYTE &&
datatype != DataBuffer.TYPE_USHORT) {
return false;
}
//
// Check dst sample sizes. All must be 8 or 16 bits.
//
SampleModel dstSM = dst.getSampleModel();
dstNbits = dstSM.getSampleSize(0);
if (!(dstNbits == 8 || dstNbits == 16)) {
return false;
}
for (int i=1; i<src.getNumBands(); i++) {
int bandSize = dstSM.getSampleSize(i);
if (bandSize != dstNbits) {
return false;
}
}
//
// Check src sample sizes. All must be the same size
//
SampleModel srcSM = src.getSampleModel();
srcNbits = srcSM.getSampleSize(0);
if (srcNbits > 16) {
return false;
}
for (int i=1; i<src.getNumBands(); i++) {
int bandSize = srcSM.getSampleSize(i);
if (bandSize != srcNbits) {
return false;
}
}
if (dstSM instanceof ComponentSampleModel) {
ComponentSampleModel dsm = (ComponentSampleModel)dstSM;
if (dsm.getPixelStride() != dst.getNumBands()) {
return false;
}
}
if (srcSM instanceof ComponentSampleModel) {
ComponentSampleModel csm = (ComponentSampleModel)srcSM;
if (csm.getPixelStride() != src.getNumBands()) {
return false;
}
}
return true;
}
/**
* Rescales the source BufferedImage.
* If the color model in the source image is not the same as that
* in the destination image, the pixels will be converted
* in the destination. If the destination image is null,
* a BufferedImage will be created with the source ColorModel.
* An IllegalArgumentException may be thrown if the number of
* scaling factors/offsets in this object does not meet the
* restrictions stated in the class comments above, or if the
* source image has an IndexColorModel.
* @param src the <code>BufferedImage</code> to be filtered
* @param dst the destination for the filtering operation
* or <code>null</code>
* @return the filtered <code>BufferedImage</code>.
* @throws IllegalArgumentException if the <code>ColorModel</code>
* of <code>src</code> is an <code>IndexColorModel</code>,
* or if the number of scaling factors and offsets in this
* <code>RescaleOp</code> do not meet the requirements
* stated in the class comments.
*/
public final BufferedImage filter (BufferedImage src, BufferedImage dst) {
ColorModel srcCM = src.getColorModel();
ColorModel dstCM;
int numSrcColorComp = srcCM.getNumColorComponents();
int scaleConst = length;
if (srcCM instanceof IndexColorModel) {
throw new
IllegalArgumentException("Rescaling cannot be "+
"performed on an indexed image");
}
if (scaleConst != 1 && scaleConst != numSrcColorComp &&
scaleConst != srcCM.getNumComponents())
{
throw new IllegalArgumentException("Number of scaling constants "+
"does not equal the number of"+
" of color or color/alpha "+
" components");
}
boolean needToConvert = false;
boolean needToDraw = false;
// Include alpha
if (scaleConst > numSrcColorComp && srcCM.hasAlpha()) {
scaleConst = numSrcColorComp+1;
}
int width = src.getWidth();
int height = src.getHeight();
BufferedImage origDst = dst;
if (dst == null) {
dst = createCompatibleDestImage(src, null);
dstCM = srcCM;
}
else {
if (width != dst.getWidth()) {
throw new
IllegalArgumentException("Src width ("+width+
") not equal to dst width ("+
dst.getWidth()+")");
}
if (height != dst.getHeight()) {
throw new
IllegalArgumentException("Src height ("+height+
") not equal to dst height ("+
dst.getHeight()+")");
}
dstCM = dst.getColorModel();
if(srcCM.getColorSpace().getType() !=
dstCM.getColorSpace().getType()) {
needToConvert = true;
dst = createCompatibleDestImage(src, null);
}
}
//
// Try to use a native BI rescale operation first
//
if (ImagingLib.filter(this, src, dst) == null) {
if (src.getRaster().getNumBands() !=
dst.getRaster().getNumBands()) {
needToDraw = true;
dst = createCompatibleDestImage(src, null);
}
//
// Native BI rescale failed - convert to rasters
//
WritableRaster srcRaster = src.getRaster();
WritableRaster dstRaster = dst.getRaster();
//
// Call the raster filter method
//
filterRasterImpl(srcRaster, dstRaster, scaleConst, false);
}
if (needToDraw) {
Graphics2D g = origDst.createGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(dst, 0, 0, width, height, null);
g.dispose();
}
if (needToConvert) {
// ColorModels are not the same
ColorConvertOp ccop = new ColorConvertOp(hints);
dst = ccop.filter(dst, origDst);
}
return dst;
}
/**
* Rescales the pixel data in the source Raster.
* If the destination Raster is null, a new Raster will be created.
* The source and destination must have the same number of bands.
* Otherwise, an IllegalArgumentException is thrown.
* Note that the number of scaling factors/offsets in this object must
* meet the restrictions stated in the class comments above.
* Otherwise, an IllegalArgumentException is thrown.
* @param src the <code>Raster</code> to be filtered
* @param dst the destination for the filtering operation
* or <code>null</code>
* @return the filtered <code>WritableRaster</code>.
* @throws IllegalArgumentException if <code>src</code> and
* <code>dst</code> do not have the same number of bands,
* or if the number of scaling factors and offsets in this
* <code>RescaleOp</code> do not meet the requirements
* stated in the class comments.
*/
public final WritableRaster filter (Raster src, WritableRaster dst) {
return filterRasterImpl(src, dst, length, true);
}
private WritableRaster filterRasterImpl(Raster src, WritableRaster dst,
int scaleConst, boolean sCheck) {
int numBands = src.getNumBands();
int width = src.getWidth();
int height = src.getHeight();
int[] srcPix = null;
int step = 0;
int tidx = 0;
// Create a new destination Raster, if needed
if (dst == null) {
dst = createCompatibleDestRaster(src);
}
else if (height != dst.getHeight() || width != dst.getWidth()) {
throw new
IllegalArgumentException("Width or height of Rasters do not "+
"match");
}
else if (numBands != dst.getNumBands()) {
// Make sure that the number of bands are equal
throw new IllegalArgumentException("Number of bands in src "
+ numBands
+ " does not equal number of bands in dest "
+ dst.getNumBands());
}
// Make sure that the arrays match
// Make sure that the low/high/constant arrays match
if (sCheck && scaleConst != 1 && scaleConst != src.getNumBands()) {
throw new IllegalArgumentException("Number of scaling constants "+
"does not equal the number of"+
" of bands in the src raster");
}
//
// Try for a native raster rescale first
//
if (ImagingLib.filter(this, src, dst) != null) {
return dst;
}
//
// Native raster rescale failed.
// Try to see if a lookup operation can be used
//
if (canUseLookup(src, dst)) {
int srcNgray = (1 << srcNbits);
int dstNgray = (1 << dstNbits);
if (dstNgray == 256) {
ByteLookupTable lut = createByteLut(scaleFactors, offsets,
numBands, srcNgray);
LookupOp op = new LookupOp(lut, hints);
op.filter(src, dst);
} else {
ShortLookupTable lut = createShortLut(scaleFactors, offsets,
numBands, srcNgray);
LookupOp op = new LookupOp(lut, hints);
op.filter(src, dst);
}
} else {
//
// Fall back to the slow code
//
if (scaleConst > 1) {
step = 1;
}
int sminX = src.getMinX();
int sY = src.getMinY();
int dminX = dst.getMinX();
int dY = dst.getMinY();
int sX;
int dX;
//
// Determine bits per band to determine maxval for clamps.
// The min is assumed to be zero.
// REMIND: This must change if we ever support signed data types.
//
int nbits;
int dstMax[] = new int[numBands];
int dstMask[] = new int[numBands];
SampleModel dstSM = dst.getSampleModel();
for (int z=0; z<numBands; z++) {
nbits = dstSM.getSampleSize(z);
dstMax[z] = (1 << nbits) - 1;
dstMask[z] = ~(dstMax[z]);
}
int val;
for (int y=0; y < height; y++, sY++, dY++) {
dX = dminX;
sX = sminX;
for (int x = 0; x < width; x++, sX++, dX++) {
// Get data for all bands at this x,y position
srcPix = src.getPixel(sX, sY, srcPix);
tidx = 0;
for (int z=0; z<numBands; z++, tidx += step) {
if ((scaleConst == 1 || scaleConst == 3) &&
(z == 3) && (numBands == 4)) {
val = srcPix[z];
} else {
val = (int)(srcPix[z]*scaleFactors[tidx]
+ offsets[tidx]);
}
// Clamp
if ((val & dstMask[z]) != 0) {
if (val < 0) {
val = 0;
} else {
val = dstMax[z];
}
}
srcPix[z] = val;
}
// Put it back for all bands
dst.setPixel(dX, dY, srcPix);
}
}
}
return dst;
}
/**
* Returns the bounding box of the rescaled destination image. Since
* this is not a geometric operation, the bounding box does not
* change.
*/
public final Rectangle2D getBounds2D (BufferedImage src) {
return getBounds2D(src.getRaster());
}
/**
* Returns the bounding box of the rescaled destination Raster. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param src the rescaled destination <code>Raster</code>
* @return the bounds of the specified <code>Raster</code>.
*/
public final Rectangle2D getBounds2D (Raster src) {
return src.getBounds();
}
/**
* Creates a zeroed destination image with the correct size and number of
* bands.
* @param src Source image for the filter operation.
* @param destCM ColorModel of the destination. If null, the
* ColorModel of the source will be used.
* @return the zeroed-destination image.
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM) {
BufferedImage image;
if (destCM == null) {
ColorModel cm = src.getColorModel();
image = new BufferedImage(cm,
src.getRaster().createCompatibleWritableRaster(),
cm.isAlphaPremultiplied(),
null);
}
else {
int w = src.getWidth();
int h = src.getHeight();
image = new BufferedImage (destCM,
destCM.createCompatibleWritableRaster(w, h),
destCM.isAlphaPremultiplied(), null);
}
return image;
}
/**
* Creates a zeroed-destination <code>Raster</code> with the correct
* size and number of bands, given this source.
* @param src the source <code>Raster</code>
* @return the zeroed-destination <code>Raster</code>.
*/
public WritableRaster createCompatibleDestRaster (Raster src) {
return src.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
}
/**
* Returns the location of the destination point given a
* point in the source. If dstPt is non-null, it will
* be used to hold the return value. Since this is not a geometric
* operation, the srcPt will equal the dstPt.
* @param srcPt a point in the source image
* @param dstPt the destination point or <code>null</code>
* @return the location of the destination point.
*/
public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
if (dstPt == null) {
dstPt = new Point2D.Float();
}
dstPt.setLocation(srcPt.getX(), srcPt.getY());
return dstPt;
}
/**
* Returns the rendering hints for this op.
* @return the rendering hints of this <code>RescaleOp</code>.
*/
public final RenderingHints getRenderingHints() {
return hints;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* This class defines a lookup table object. The output of a
* lookup operation using an object of this class is interpreted
* as an unsigned short quantity. The lookup table contains short
* data arrays for one or more bands (or components) of an image,
* and it contains an offset which will be subtracted from the
* input values before indexing the arrays. This allows an array
* smaller than the native data size to be provided for a
* constrained input. If there is only one array in the lookup
* table, it will be applied to all bands.
*
* @see ByteLookupTable
* @see LookupOp
*/
public class ShortLookupTable extends LookupTable {
/**
* Constants
*/
short data[][];
/**
* Constructs a ShortLookupTable object from an array of short
* arrays representing a lookup table for each
* band. The offset will be subtracted from the input
* values before indexing into the arrays. The number of
* bands is the length of the data argument. The
* data array for each band is stored as a reference.
* @param offset the value subtracted from the input values
* before indexing into the arrays
* @param data an array of short arrays representing a lookup
* table for each band
*/
public ShortLookupTable(int offset, short data[][]) {
super(offset,data.length);
numComponents = data.length;
numEntries = data[0].length;
this.data = new short[numComponents][];
// Allocate the array and copy the data reference
for (int i=0; i < numComponents; i++) {
this.data[i] = data[i];
}
}
/**
* Constructs a ShortLookupTable object from an array
* of shorts representing a lookup table for each
* band. The offset will be subtracted from the input
* values before indexing into the array. The
* data array is stored as a reference.
* @param offset the value subtracted from the input values
* before indexing into the arrays
* @param data an array of shorts
*/
public ShortLookupTable(int offset, short data[]) {
super(offset,data.length);
numComponents = 1;
numEntries = data.length;
this.data = new short[1][];
this.data[0] = data;
}
/**
* Returns the lookup table data by reference. If this ShortLookupTable
* was constructed using a single short array, the length of the returned
* array is one.
* @return ShortLookupTable data array.
*/
public final short[][] getTable(){
return data;
}
/**
* Returns an array of samples of a pixel, translated with the lookup
* table. The source and destination array can be the same array.
* Array <code>dst</code> is returned.
*
* @param src the source array.
* @param dst the destination array. This array must be at least as
* long as <code>src</code>. If <code>dst</code> is
* <code>null</code>, a new array will be allocated having the
* same length as <code>src</code>.
* @return the array <code>dst</code>, an <code>int</code> array of
* samples.
* @exception ArrayIndexOutOfBoundsException if <code>src</code> is
* longer than <code>dst</code> or if for any element
* <code>i</code> of <code>src</code>,
* {@code (src[i]&0xffff)-offset} is either less than
* zero or greater than or equal to the length of the
* lookup table for any band.
*/
public int[] lookupPixel(int[] src, int[] dst){
if (dst == null) {
// Need to alloc a new destination array
dst = new int[src.length];
}
if (numComponents == 1) {
// Apply one LUT to all channels
for (int i=0; i < src.length; i++) {
int s = (src[i]&0xffff) - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = (int) data[0][s];
}
}
else {
for (int i=0; i < src.length; i++) {
int s = (src[i]&0xffff) - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = (int) data[i][s];
}
}
return dst;
}
/**
* Returns an array of samples of a pixel, translated with the lookup
* table. The source and destination array can be the same array.
* Array <code>dst</code> is returned.
*
* @param src the source array.
* @param dst the destination array. This array must be at least as
* long as <code>src</code>. If <code>dst</code> is
* <code>null</code>, a new array will be allocated having the
* same length as <code>src</code>.
* @return the array <code>dst</code>, an <code>int</code> array of
* samples.
* @exception ArrayIndexOutOfBoundsException if <code>src</code> is
* longer than <code>dst</code> or if for any element
* <code>i</code> of <code>src</code>,
* {@code (src[i]&0xffff)-offset} is either less than
* zero or greater than or equal to the length of the
* lookup table for any band.
*/
public short[] lookupPixel(short[] src, short[] dst){
if (dst == null) {
// Need to alloc a new destination array
dst = new short[src.length];
}
if (numComponents == 1) {
// Apply one LUT to all channels
for (int i=0; i < src.length; i++) {
int s = (src[i]&0xffff) - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = data[0][s];
}
}
else {
for (int i=0; i < src.length; i++) {
int s = (src[i]&0xffff) - offset;
if (s < 0) {
throw new ArrayIndexOutOfBoundsException("src["+i+
"]-offset is "+
"less than zero");
}
dst[i] = data[i][s];
}
}
return dst;
}
}

View File

@@ -0,0 +1,801 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.util.Arrays;
/**
* This class represents pixel data packed such that the N samples which make
* up a single pixel are stored in a single data array element, and each data
* data array element holds samples for only one pixel.
* This class supports
* {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
* {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
* {@link DataBuffer#TYPE_INT TYPE_INT} data types.
* All data array elements reside
* in the first bank of a DataBuffer. Accessor methods are provided so
* that the image data can be manipulated directly. Scanline stride is the
* number of data array elements between a given sample and the corresponding
* sample in the same column of the next scanline. Bit masks are the masks
* required to extract the samples representing the bands of the pixel.
* Bit offsets are the offsets in bits into the data array
* element of the samples representing the bands of the pixel.
* <p>
* The following code illustrates extracting the bits of the sample
* representing band <code>b</code> for pixel <code>x,y</code>
* from DataBuffer <code>data</code>:
* <pre>{@code
* int sample = data.getElem(y * scanlineStride + x);
* sample = (sample & bitMasks[b]) >>> bitOffsets[b];
* }</pre>
*/
public class SinglePixelPackedSampleModel extends SampleModel
{
/** Bit masks for all bands of the image data. */
private int bitMasks[];
/** Bit Offsets for all bands of the image data. */
private int bitOffsets[];
/** Bit sizes for all the bands of the image data. */
private int bitSizes[];
/** Maximum bit size. */
private int maxBitSize;
/** Line stride of the region of image data described by this
* SinglePixelPackedSampleModel.
*/
private int scanlineStride;
private static native void initIDs();
static {
ColorModel.loadLibraries();
initIDs();
}
/**
* Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
* Each sample is stored in a data array element in the position of
* its corresponding bit mask. Each bit mask must be contiguous and
* masks must not overlap. Bit masks exceeding data type capacity are
* truncated.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of the
* image data described.
* @param h The height (in pixels) of the region of the
* image data described.
* @param bitMasks The bit masks for all bands.
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int bitMasks[]) {
this(dataType, w, h, w, bitMasks);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
}
/**
* Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
* and a scanline stride equal to scanlineStride data array elements.
* Each sample is stored in a data array element in the position of
* its corresponding bit mask. Each bit mask must be contiguous and
* masks must not overlap. Bit masks exceeding data type capacity are
* truncated.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param scanlineStride The line stride of the image data.
* @param bitMasks The bit masks for all bands.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
* @throws IllegalArgumentException if any mask in
* <code>bitMask</code> is not contiguous
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int scanlineStride, int bitMasks[]) {
super(dataType, w, h, bitMasks.length);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
this.dataType = dataType;
this.bitMasks = (int[]) bitMasks.clone();
this.scanlineStride = scanlineStride;
this.bitOffsets = new int[numBands];
this.bitSizes = new int[numBands];
int maxMask = (int)((1L << DataBuffer.getDataTypeSize(dataType)) - 1);
this.maxBitSize = 0;
for (int i=0; i<numBands; i++) {
int bitOffset = 0, bitSize = 0, mask;
this.bitMasks[i] &= maxMask;
mask = this.bitMasks[i];
if (mask != 0) {
while ((mask & 1) == 0) {
mask = mask >>> 1;
bitOffset++;
}
while ((mask & 1) == 1) {
mask = mask >>> 1;
bitSize++;
}
if (mask != 0) {
throw new IllegalArgumentException("Mask "+bitMasks[i]+
" must be contiguous");
}
}
bitOffsets[i] = bitOffset;
bitSizes[i] = bitSize;
if (bitSize > maxBitSize) {
maxBitSize = bitSize;
}
}
}
/**
* Returns the number of data elements needed to transfer one pixel
* via the getDataElements and setDataElements methods.
* For a SinglePixelPackedSampleModel, this is one.
*/
public int getNumDataElements() {
return 1;
}
/**
* Returns the size of the buffer (in data array elements)
* needed for a data buffer that matches this
* SinglePixelPackedSampleModel.
*/
private long getBufferSize() {
long size = scanlineStride * (height-1) + width;
return size;
}
/**
* Creates a new SinglePixelPackedSampleModel with the specified
* width and height. The new SinglePixelPackedSampleModel will have the
* same storage data type and bit masks as this
* SinglePixelPackedSampleModel.
* @param w the width of the resulting <code>SampleModel</code>
* @param h the height of the resulting <code>SampleModel</code>
* @return a <code>SinglePixelPackedSampleModel</code> with the
* specified width and height.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h,
bitMasks);
return sampleModel;
}
/**
* Creates a DataBuffer that corresponds to this
* SinglePixelPackedSampleModel. The DataBuffer's data type and size
* will be consistent with this SinglePixelPackedSampleModel. The
* DataBuffer will have a single bank.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = (int)getBufferSize();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size);
break;
}
return dataBuffer;
}
/** Returns the number of bits per sample for all bands. */
public int[] getSampleSize() {
return bitSizes.clone();
}
/** Returns the number of bits per sample for the specified band. */
public int getSampleSize(int band) {
return bitSizes[band];
}
/** Returns the offset (in data array elements) of pixel (x,y).
* The data element containing pixel <code>x,y</code>
* can be retrieved from a DataBuffer <code>data</code> with a
* SinglePixelPackedSampleModel <code>sppsm</code> as:
* <pre>
* data.getElem(sppsm.getOffset(x, y));
* </pre>
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @return the offset of the specified pixel.
*/
public int getOffset(int x, int y) {
int offset = y * scanlineStride + x;
return offset;
}
/** Returns the bit offsets into the data array element representing
* a pixel for all bands.
* @return the bit offsets representing a pixel for all bands.
*/
public int [] getBitOffsets() {
return (int[])bitOffsets.clone();
}
/** Returns the bit masks for all bands.
* @return the bit masks for all bands.
*/
public int [] getBitMasks() {
return (int[])bitMasks.clone();
}
/** Returns the scanline stride of this SinglePixelPackedSampleModel.
* @return the scanline stride of this
* <code>SinglePixelPackedSampleModel</code>.
*/
public int getScanlineStride() {
return scanlineStride;
}
/**
* This creates a new SinglePixelPackedSampleModel with a subset of the
* bands of this SinglePixelPackedSampleModel. The new
* SinglePixelPackedSampleModel can be used with any DataBuffer that the
* existing SinglePixelPackedSampleModel can be used with. The new
* SinglePixelPackedSampleModel/DataBuffer combination will represent
* an image with a subset of the bands of the original
* SinglePixelPackedSampleModel/DataBuffer combination.
* @exception RasterFormatException if the length of the bands argument is
* greater than the number of bands in
* the sample model.
*/
public SampleModel createSubsetSampleModel(int bands[]) {
if (bands.length > numBands)
throw new RasterFormatException("There are only " +
numBands +
" bands");
int newBitMasks[] = new int[bands.length];
for (int i=0; i<bands.length; i++)
newBitMasks[i] = bitMasks[bands[i]];
return new SinglePixelPackedSampleModel(this.dataType, width, height,
this.scanlineStride, newBitMasks);
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a SinglePixelPackedSampleModel, the array will
* have one element, and the type will be the same as the storage
* data type. Generally, obj
* should be passed in as null, so that the Object will be created
* automatically and will be of the right primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm1</code>, to
* DataBuffer <code>db2</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* SinglePixelPackedSampleModel sppsm1, sppsm2;
* DataBufferInt db1, db2;
* sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* If obj is non-null, it should be a primitive array of type TransferType.
* Otherwise, a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is non-null and is not large enough to hold
* the pixel data.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param obj If non-null, a primitive array in which to return
* the pixel data.
* @param data The DataBuffer containing the image data.
* @return the data for the specified pixel.
* @see #setDataElements(int, int, Object, DataBuffer)
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null)
bdata = new byte[1];
else
bdata = (byte[])obj;
bdata[0] = (byte)data.getElem(y * scanlineStride + x);
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
short[] sdata;
if (obj == null)
sdata = new short[1];
else
sdata = (short[])obj;
sdata[0] = (short)data.getElem(y * scanlineStride + x);
obj = (Object)sdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null)
idata = new int[1];
else
idata = (int[])obj;
idata[0] = data.getElem(y * scanlineStride + x);
obj = (Object)idata;
break;
}
return obj;
}
/**
* Returns all samples in for the specified pixel in an int array.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data.
* @return all samples for the specified pixel.
* @see #setPixel(int, int, int[], DataBuffer)
*/
public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixels[];
if (iArray == null) {
pixels = new int [numBands];
} else {
pixels = iArray;
}
int value = data.getElem(y * scanlineStride + x);
for (int i=0; i<numBands; i++) {
pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
}
return pixels;
}
/**
* Returns all samples for the specified rectangle of pixels in
* an int array, one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param iArray If non-null, returns the samples in this array.
* @param data The DataBuffer containing the image data.
* @return all samples for the specified region of pixels.
* @see #setPixels(int, int, int, int, int[], DataBuffer)
*/
public int[] getPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
int x1 = x + w;
int y1 = y + h;
if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
{
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixels[];
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int [w*h*numBands];
}
int lineOffset = y*scanlineStride + x;
int dstOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
for (int k=0; k < numBands; k++) {
pixels[dstOffset++] =
((value & bitMasks[k]) >>> bitOffsets[k]);
}
}
lineOffset += scanlineStride;
}
return pixels;
}
/**
* Returns as int the sample in a specified band for the pixel
* located at (x,y).
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to return.
* @param data The DataBuffer containing the image data.
* @return the sample in a specified band for the specified
* pixel.
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int sample = data.getElem(y * scanlineStride + x);
return ((sample & bitMasks[b]) >>> bitOffsets[b]);
}
/**
* Returns the samples for a specified band for the specified rectangle
* of pixels in an int array, one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param b The band to return.
* @param iArray If non-null, returns the samples in this array.
* @param data The DataBuffer containing the image data.
* @return the samples for the specified band for the specified
* region of pixels.
* @see #setSamples(int, int, int, int, int, int[], DataBuffer)
*/
public int[] getSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int samples[];
if (iArray != null) {
samples = iArray;
} else {
samples = new int [w*h];
}
int lineOffset = y*scanlineStride + x;
int dstOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
samples[dstOffset++] =
((value & bitMasks[b]) >>> bitOffsets[b]);
}
lineOffset += scanlineStride;
}
return samples;
}
/**
* Sets the data for a single pixel in the specified DataBuffer from a
* primitive array of type TransferType. For a
* SinglePixelPackedSampleModel, only the first element of the array
* will hold valid data, and the type of the array must be the same as
* the storage data type of the SinglePixelPackedSampleModel.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm1</code>,
* to DataBuffer <code>db2</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* SinglePixelPackedSampleModel sppsm1, sppsm2;
* DataBufferInt db1, db2;
* sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* obj must be a primitive array of type TransferType. Otherwise,
* a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is not large enough to hold the pixel data.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param obj A primitive array containing pixel data.
* @param data The DataBuffer containing the image data.
* @see #getDataElements(int, int, Object, DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
break;
case DataBuffer.TYPE_USHORT:
short[] sarray = (short[])obj;
data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
data.setElem(y*scanlineStride+x, iarray[0]);
break;
}
}
/**
* Sets a pixel in the DataBuffer using an int array of samples for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param iArray The input samples in an int array.
* @param data The DataBuffer containing the image data.
* @see #getPixel(int, int, int[], DataBuffer)
*/
public void setPixel(int x, int y,
int iArray[],
DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y * scanlineStride + x;
int value = data.getElem(lineOffset);
for (int i=0; i < numBands; i++) {
value &= ~bitMasks[i];
value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
}
data.setElem(lineOffset, value);
}
/**
* Sets all samples for a rectangle of pixels from an int array containing
* one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param iArray The input samples in an int array.
* @param data The DataBuffer containing the image data.
* @see #getPixels(int, int, int, int, int[], DataBuffer)
*/
public void setPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
int x1 = x + w;
int y1 = y + h;
if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
{
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y*scanlineStride + x;
int srcOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
for (int k=0; k < numBands; k++) {
value &= ~bitMasks[k];
int srcValue = iArray[srcOffset++];
value |= ((srcValue << bitOffsets[k])
& bitMasks[k]);
}
data.setElem(lineOffset+j, value);
}
lineOffset += scanlineStride;
}
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using an int for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as an int.
* @param data The DataBuffer containing the image data.
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b, int s,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int value = data.getElem(y*scanlineStride + x);
value &= ~bitMasks[b];
value |= (s << bitOffsets[b]) & bitMasks[b];
data.setElem(y*scanlineStride + x,value);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from an int array containing one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param b The band to set.
* @param iArray The input samples in an int array.
* @param data The DataBuffer containing the image data.
* @see #getSamples(int, int, int, int, int, int[], DataBuffer)
*/
public void setSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y*scanlineStride + x;
int srcOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
value &= ~bitMasks[b];
int sample = iArray[srcOffset++];
value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
data.setElem(lineOffset+j,value);
}
lineOffset += scanlineStride;
}
}
public boolean equals(Object o) {
if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
return false;
}
SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o;
return this.width == that.width &&
this.height == that.height &&
this.numBands == that.numBands &&
this.dataType == that.dataType &&
Arrays.equals(this.bitMasks, that.bitMasks) &&
Arrays.equals(this.bitOffsets, that.bitOffsets) &&
Arrays.equals(this.bitSizes, that.bitSizes) &&
this.maxBitSize == that.maxBitSize &&
this.scanlineStride == that.scanlineStride;
}
// If we implement equals() we must also implement hashCode
public int hashCode() {
int hash = 0;
hash = width;
hash <<= 8;
hash ^= height;
hash <<= 8;
hash ^= numBands;
hash <<= 8;
hash ^= dataType;
hash <<= 8;
for (int i = 0; i < bitMasks.length; i++) {
hash ^= bitMasks[i];
hash <<= 8;
}
for (int i = 0; i < bitOffsets.length; i++) {
hash ^= bitOffsets[i];
hash <<= 8;
}
for (int i = 0; i < bitSizes.length; i++) {
hash ^= bitSizes[i];
hash <<= 8;
}
hash ^= maxBitSize;
hash <<= 8;
hash ^= scanlineStride;
return hash;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
/**
* An interface for objects that wish to be informed when tiles
* of a WritableRenderedImage become modifiable by some writer via
* a call to getWritableTile, and when they become unmodifiable via
* the last call to releaseWritableTile.
*
* @see WritableRenderedImage
*
* @author Thomas DeWeese
* @author Daniel Rice
*/
public interface TileObserver {
/**
* A tile is about to be updated (it is either about to be grabbed
* for writing, or it is being released from writing).
*
* @param source the image that owns the tile.
* @param tileX the X index of the tile that is being updated.
* @param tileY the Y index of the tile that is being updated.
* @param willBeWritable If true, the tile will be grabbed for writing;
* otherwise it is being released.
*/
public void tileUpdate(WritableRenderedImage source,
int tileX, int tileY,
boolean willBeWritable);
}

View File

@@ -0,0 +1,342 @@
/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.Toolkit;
import java.awt.Transparency;
/**
* VolatileImage is an image which can lose its
* contents at any time due to circumstances beyond the control of the
* application (e.g., situations caused by the operating system or by
* other applications). Because of the potential for hardware acceleration,
* a VolatileImage object can have significant performance benefits on
* some platforms.
* <p>
* The drawing surface of an image (the memory where the image contents
* actually reside) can be lost or invalidated, causing the contents of that
* memory to go away. The drawing surface thus needs to be restored
* or recreated and the contents of that surface need to be
* re-rendered. VolatileImage provides an interface for
* allowing the user to detect these problems and fix them
* when they occur.
* <p>
* When a VolatileImage object is created, limited system resources
* such as video memory (VRAM) may be allocated in order to support
* the image.
* When a VolatileImage object is no longer used, it may be
* garbage-collected and those system resources will be returned,
* but this process does not happen at guaranteed times.
* Applications that create many VolatileImage objects (for example,
* a resizing window may force recreation of its back buffer as the
* size changes) may run out of optimal system resources for new
* VolatileImage objects simply because the old objects have not
* yet been removed from the system.
* (New VolatileImage objects may still be created, but they
* may not perform as well as those created in accelerated
* memory).
* The flush method may be called at any time to proactively release
* the resources used by a VolatileImage so that it does not prevent
* subsequent VolatileImage objects from being accelerated.
* In this way, applications can have more control over the state
* of the resources taken up by obsolete VolatileImage objects.
* <p>
* This image should not be subclassed directly but should be created
* by using the {@link java.awt.Component#createVolatileImage(int, int)
* Component.createVolatileImage} or
* {@link java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int)
* GraphicsConfiguration.createCompatibleVolatileImage(int, int)} methods.
* <P>
* An example of using a VolatileImage object follows:
* <pre>
* // image creation
* VolatileImage vImg = createVolatileImage(w, h);
*
*
* // rendering to the image
* void renderOffscreen() {
* do {
* if (vImg.validate(getGraphicsConfiguration()) ==
* VolatileImage.IMAGE_INCOMPATIBLE)
* {
* // old vImg doesn't work with new GraphicsConfig; re-create it
* vImg = createVolatileImage(w, h);
* }
* Graphics2D g = vImg.createGraphics();
* //
* // miscellaneous rendering commands...
* //
* g.dispose();
* } while (vImg.contentsLost());
* }
*
*
* // copying from the image (here, gScreen is the Graphics
* // object for the onscreen window)
* do {
* int returnCode = vImg.validate(getGraphicsConfiguration());
* if (returnCode == VolatileImage.IMAGE_RESTORED) {
* // Contents need to be restored
* renderOffscreen(); // restore contents
* } else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
* // old vImg doesn't work with new GraphicsConfig; re-create it
* vImg = createVolatileImage(w, h);
* renderOffscreen();
* }
* gScreen.drawImage(vImg, 0, 0, this);
* } while (vImg.contentsLost());
* </pre>
* <P>
* Note that this class subclasses from the {@link Image} class, which
* includes methods that take an {@link ImageObserver} parameter for
* asynchronous notifications as information is received from
* a potential {@link ImageProducer}. Since this <code>VolatileImage</code>
* is not loaded from an asynchronous source, the various methods that take
* an <code>ImageObserver</code> parameter will behave as if the data has
* already been obtained from the <code>ImageProducer</code>.
* Specifically, this means that the return values from such methods
* will never indicate that the information is not yet available and
* the <code>ImageObserver</code> used in such methods will never
* need to be recorded for an asynchronous callback notification.
* @since 1.4
*/
public abstract class VolatileImage extends Image implements Transparency
{
// Return codes for validate() method
/**
* Validated image is ready to use as-is.
*/
public static final int IMAGE_OK = 0;
/**
* Validated image has been restored and is now ready to use.
* Note that restoration causes contents of the image to be lost.
*/
public static final int IMAGE_RESTORED = 1;
/**
* Validated image is incompatible with supplied
* <code>GraphicsConfiguration</code> object and should be
* re-created as appropriate. Usage of the image as-is
* after receiving this return code from <code>validate</code>
* is undefined.
*/
public static final int IMAGE_INCOMPATIBLE = 2;
/**
* Returns a static snapshot image of this object. The
* <code>BufferedImage</code> returned is only current with
* the <code>VolatileImage</code> at the time of the request
* and will not be updated with any future changes to the
* <code>VolatileImage</code>.
* @return a {@link BufferedImage} representation of this
* <code>VolatileImage</code>
* @see BufferedImage
*/
public abstract BufferedImage getSnapshot();
/**
* Returns the width of the <code>VolatileImage</code>.
* @return the width of this <code>VolatileImage</code>.
*/
public abstract int getWidth();
/**
* Returns the height of the <code>VolatileImage</code>.
* @return the height of this <code>VolatileImage</code>.
*/
public abstract int getHeight();
// Image overrides
/**
* This returns an ImageProducer for this VolatileImage.
* Note that the VolatileImage object is optimized for
* rendering operations and blitting to the screen or other
* VolatileImage objects, as opposed to reading back the
* pixels of the image. Therefore, operations such as
* <code>getSource</code> may not perform as fast as
* operations that do not rely on reading the pixels.
* Note also that the pixel values read from the image are current
* with those in the image only at the time that they are
* retrieved. This method takes a snapshot
* of the image at the time the request is made and the
* ImageProducer object returned works with
* that static snapshot image, not the original VolatileImage.
* Calling getSource()
* is equivalent to calling getSnapshot().getSource().
* @return an {@link ImageProducer} that can be used to produce the
* pixels for a <code>BufferedImage</code> representation of
* this Image.
* @see ImageProducer
* @see #getSnapshot()
*/
public ImageProducer getSource() {
// REMIND: Make sure this functionality is in line with the
// spec. In particular, we are returning the Source for a
// static image (the snapshot), not a changing image (the
// VolatileImage). So if the user expects the Source to be
// up-to-date with the current contents of the VolatileImage,
// they will be disappointed...
// REMIND: This assumes that getSnapshot() returns something
// valid and not the default null object returned by this class
// (so it assumes that the actual VolatileImage object is
// subclassed off something that does the right thing
// (e.g., SunVolatileImage).
return getSnapshot().getSource();
}
// REMIND: if we want any decent performance for getScaledInstance(),
// we should override the Image implementation of it...
/**
* This method returns a {@link Graphics2D}, but is here
* for backwards compatibility. {@link #createGraphics() createGraphics} is more
* convenient, since it is declared to return a
* <code>Graphics2D</code>.
* @return a <code>Graphics2D</code>, which can be used to draw into
* this image.
*/
public Graphics getGraphics() {
return createGraphics();
}
/**
* Creates a <code>Graphics2D</code>, which can be used to draw into
* this <code>VolatileImage</code>.
* @return a <code>Graphics2D</code>, used for drawing into this
* image.
*/
public abstract Graphics2D createGraphics();
// Volatile management methods
/**
* Attempts to restore the drawing surface of the image if the surface
* had been lost since the last <code>validate</code> call. Also
* validates this image against the given GraphicsConfiguration
* parameter to see whether operations from this image to the
* GraphicsConfiguration are compatible. An example of an
* incompatible combination might be a situation where a VolatileImage
* object was created on one graphics device and then was used
* to render to a different graphics device. Since VolatileImage
* objects tend to be very device-specific, this operation might
* not work as intended, so the return code from this validate
* call would note that incompatibility. A null or incorrect
* value for gc may cause incorrect values to be returned from
* <code>validate</code> and may cause later problems with rendering.
*
* @param gc a <code>GraphicsConfiguration</code> object for this
* image to be validated against. A null gc implies that the
* validate method should skip the compatibility test.
* @return <code>IMAGE_OK</code> if the image did not need validation<BR>
* <code>IMAGE_RESTORED</code> if the image needed restoration.
* Restoration implies that the contents of the image may have
* been affected and the image may need to be re-rendered.<BR>
* <code>IMAGE_INCOMPATIBLE</code> if the image is incompatible
* with the <code>GraphicsConfiguration</code> object passed
* into the <code>validate</code> method. Incompatibility
* implies that the image may need to be recreated with a
* new <code>Component</code> or
* <code>GraphicsConfiguration</code> in order to get an image
* that can be used successfully with this
* <code>GraphicsConfiguration</code>.
* An incompatible image is not checked for whether restoration
* was necessary, so the state of the image is unchanged
* after a return value of <code>IMAGE_INCOMPATIBLE</code>
* and this return value implies nothing about whether the
* image needs to be restored.
* @see java.awt.GraphicsConfiguration
* @see java.awt.Component
* @see #IMAGE_OK
* @see #IMAGE_RESTORED
* @see #IMAGE_INCOMPATIBLE
*/
public abstract int validate(GraphicsConfiguration gc);
/**
* Returns <code>true</code> if rendering data was lost since last
* <code>validate</code> call. This method should be called by the
* application at the end of any series of rendering operations to
* or from the image to see whether
* the image needs to be validated and the rendering redone.
* @return <code>true</code> if the drawing surface needs to be restored;
* <code>false</code> otherwise.
*/
public abstract boolean contentsLost();
/**
* Returns an ImageCapabilities object which can be
* inquired as to the specific capabilities of this
* VolatileImage. This would allow programmers to find
* out more runtime information on the specific VolatileImage
* object that they have created. For example, the user
* might create a VolatileImage but the system may have
* no video memory left for creating an image of that
* size, so although the object is a VolatileImage, it is
* not as accelerated as other VolatileImage objects on
* this platform might be. The user might want that
* information to find other solutions to their problem.
* @return an <code>ImageCapabilities</code> object that contains
* the capabilities of this <code>VolatileImage</code>.
* @since 1.4
*/
public abstract ImageCapabilities getCapabilities();
/**
* The transparency value with which this image was created.
* @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int,
* int,int)
* @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int,
* int,ImageCapabilities,int)
* @see Transparency
* @since 1.5
*/
protected int transparency = TRANSLUCENT;
/**
* Returns the transparency. Returns either OPAQUE, BITMASK,
* or TRANSLUCENT.
* @return the transparency of this <code>VolatileImage</code>.
* @see Transparency#OPAQUE
* @see Transparency#BITMASK
* @see Transparency#TRANSLUCENT
* @since 1.5
*/
public int getTransparency() {
return transparency;
}
}

View File

@@ -0,0 +1,741 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.awt.Rectangle;
import java.awt.Point;
/**
* This class extends Raster to provide pixel writing capabilities.
* Refer to the class comment for Raster for descriptions of how
* a Raster stores pixels.
*
* <p> The constructors of this class are protected. To instantiate
* a WritableRaster, use one of the createWritableRaster factory methods
* in the Raster class.
*/
public class WritableRaster extends Raster {
/**
* Constructs a WritableRaster with the given SampleModel. The
* WritableRaster's upper left corner is origin and it is the
* same size as the SampleModel. A DataBuffer large enough to
* describe the WritableRaster is automatically created.
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specifies the origin.
* @throws RasterFormatException if computing either
* <code>origin.x + sampleModel.getWidth()</code> or
* <code>origin.y + sampleModel.getHeight()</code> results
* in integer overflow
*/
protected WritableRaster(SampleModel sampleModel,
Point origin) {
this(sampleModel,
sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
sampleModel.getHeight()),
origin,
null);
}
/**
* Constructs a WritableRaster with the given SampleModel and DataBuffer.
* The WritableRaster's upper left corner is origin and it is the same
* size as the SampleModel. The DataBuffer is not initialized and must
* be compatible with SampleModel.
* @param sampleModel The SampleModel that specifies the layout.
* @param dataBuffer The DataBuffer that contains the image data.
* @param origin The Point that specifies the origin.
* @throws RasterFormatException if computing either
* <code>origin.x + sampleModel.getWidth()</code> or
* <code>origin.y + sampleModel.getHeight()</code> results
* in integer overflow
*/
protected WritableRaster(SampleModel sampleModel,
DataBuffer dataBuffer,
Point origin) {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
sampleModel.getHeight()),
origin,
null);
}
/**
* Constructs a WritableRaster with the given SampleModel, DataBuffer,
* and parent. aRegion specifies the bounding rectangle of the new
* Raster. When translated into the base Raster's coordinate
* system, aRegion must be contained by the base Raster.
* (The base Raster is the Raster's ancestor which has no parent.)
* sampleModelTranslate specifies the sampleModelTranslateX and
* sampleModelTranslateY values of the new Raster.
*
* Note that this constructor should generally be called by other
* constructors or create methods, it should not be used directly.
* @param sampleModel The SampleModel that specifies the layout.
* @param dataBuffer The DataBuffer that contains the image data.
* @param aRegion The Rectangle that specifies the image area.
* @param sampleModelTranslate The Point that specifies the translation
* from SampleModel to Raster coordinates.
* @param parent The parent (if any) of this raster.
* @throws RasterFormatException if <code>aRegion</code> has width
* or height less than or equal to zero, or computing either
* <code>aRegion.x + aRegion.width</code> or
* <code>aRegion.y + aRegion.height</code> results in integer
* overflow
*/
protected WritableRaster(SampleModel sampleModel,
DataBuffer dataBuffer,
Rectangle aRegion,
Point sampleModelTranslate,
WritableRaster parent){
super(sampleModel,dataBuffer,aRegion,sampleModelTranslate,parent);
}
/** Returns the parent WritableRaster (if any) of this WritableRaster,
* or else null.
* @return the parent of this <code>WritableRaster</code>, or
* <code>null</code>.
*/
public WritableRaster getWritableParent() {
return (WritableRaster)parent;
}
/**
* Create a WritableRaster with the same size, SampleModel and DataBuffer
* as this one, but with a different location. The new WritableRaster
* will possess a reference to the current WritableRaster, accessible
* through its getParent() and getWritableParent() methods.
*
* @param childMinX X coord of the upper left corner of the new Raster.
* @param childMinY Y coord of the upper left corner of the new Raster.
* @return a <code>WritableRaster</code> the same as this one except
* for the specified location.
* @throws RasterFormatException if computing either
* <code>childMinX + this.getWidth()</code> or
* <code>childMinY + this.getHeight()</code> results in integer
* overflow
*/
public WritableRaster createWritableTranslatedChild(int childMinX,
int childMinY) {
return createWritableChild(minX,minY,width,height,
childMinX,childMinY,null);
}
/**
* Returns a new WritableRaster which shares all or part of this
* WritableRaster's DataBuffer. The new WritableRaster will
* possess a reference to the current WritableRaster, accessible
* through its getParent() and getWritableParent() methods.
*
* <p> The parentX, parentY, width and height parameters form a
* Rectangle in this WritableRaster's coordinate space, indicating
* the area of pixels to be shared. An error will be thrown if
* this Rectangle is not contained with the bounds of the current
* WritableRaster.
*
* <p> The new WritableRaster may additionally be translated to a
* different coordinate system for the plane than that used by the current
* WritableRaster. The childMinX and childMinY parameters give
* the new (x, y) coordinate of the upper-left pixel of the
* returned WritableRaster; the coordinate (childMinX, childMinY)
* in the new WritableRaster will map to the same pixel as the
* coordinate (parentX, parentY) in the current WritableRaster.
*
* <p> The new WritableRaster may be defined to contain only a
* subset of the bands of the current WritableRaster, possibly
* reordered, by means of the bandList parameter. If bandList is
* null, it is taken to include all of the bands of the current
* WritableRaster in their current order.
*
* <p> To create a new WritableRaster that contains a subregion of
* the current WritableRaster, but shares its coordinate system
* and bands, this method should be called with childMinX equal to
* parentX, childMinY equal to parentY, and bandList equal to
* null.
*
* @param parentX X coordinate of the upper left corner in this
* WritableRaster's coordinates.
* @param parentY Y coordinate of the upper left corner in this
* WritableRaster's coordinates.
* @param w Width of the region starting at (parentX, parentY).
* @param h Height of the region starting at (parentX, parentY).
* @param childMinX X coordinate of the upper left corner of
* the returned WritableRaster.
* @param childMinY Y coordinate of the upper left corner of
* the returned WritableRaster.
* @param bandList Array of band indices, or null to use all bands.
* @return a <code>WritableRaster</code> sharing all or part of the
* <code>DataBuffer</code> of this <code>WritableRaster</code>.
* @exception RasterFormatException if the subregion is outside of the
* raster bounds.
* @throws RasterFormatException if <code>w</code> or
* <code>h</code>
* is less than or equal to zero, or computing any of
* <code>parentX + w</code>, <code>parentY + h</code>,
* <code>childMinX + w</code>, or
* <code>childMinY + h</code> results in integer
* overflow
*/
public WritableRaster createWritableChild(int parentX, int parentY,
int w, int h,
int childMinX, int childMinY,
int bandList[]) {
if (parentX < this.minX) {
throw new RasterFormatException("parentX lies outside raster");
}
if (parentY < this.minY) {
throw new RasterFormatException("parentY lies outside raster");
}
if ((parentX+w < parentX) || (parentX+w > this.width + this.minX)) {
throw new RasterFormatException("(parentX + width) is outside raster");
}
if ((parentY+h < parentY) || (parentY+h > this.height + this.minY)) {
throw new RasterFormatException("(parentY + height) is outside raster");
}
SampleModel sm;
// Note: the SampleModel for the child Raster should have the same
// width and height as that for the parent, since it represents
// the physical layout of the pixel data. The child Raster's width
// and height represent a "virtual" view of the pixel data, so
// they may be different than those of the SampleModel.
if (bandList != null) {
sm = sampleModel.createSubsetSampleModel(bandList);
}
else {
sm = sampleModel;
}
int deltaX = childMinX - parentX;
int deltaY = childMinY - parentY;
return new WritableRaster(sm,
getDataBuffer(),
new Rectangle(childMinX,childMinY,
w, h),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
this);
}
/**
* Sets the data for a single pixel from a
* primitive array of type TransferType. For image data supported by
* the Java 2D(tm) API, this will be one of DataBuffer.TYPE_BYTE,
* DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
* DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
* may be in a packed format, thus increasing efficiency for data
* transfers.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if inData is not large enough to hold the pixel data.
* However, explicit bounds checking is not guaranteed.
* A ClassCastException will be thrown if the input object is not null
* and references anything other than an array of TransferType.
* @see java.awt.image.SampleModel#setDataElements(int, int, Object, DataBuffer)
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param inData An object reference to an array of type defined by
* getTransferType() and length getNumDataElements()
* containing the pixel data to place at x,y.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if inData is too small to hold the input.
*/
public void setDataElements(int x, int y, Object inData) {
sampleModel.setDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
inData, dataBuffer);
}
/**
* Sets the data for a rectangle of pixels from an input Raster.
* The input Raster must be compatible with this WritableRaster
* in that they must have the same number of bands, corresponding bands
* must have the same number of bits per sample, the TransferTypes
* and NumDataElements must be the same, and the packing used by
* the getDataElements/setDataElements must be identical.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param inRaster Raster containing data to place at x,y.
*
* @throws NullPointerException if inRaster is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds.
*/
public void setDataElements(int x, int y, Raster inRaster) {
int dstOffX = x+inRaster.getMinX();
int dstOffY = y+inRaster.getMinY();
int width = inRaster.getWidth();
int height = inRaster.getHeight();
if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
(dstOffX + width > this.minX + this.width) ||
(dstOffY + height > this.minY + this.height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int srcOffX = inRaster.getMinX();
int srcOffY = inRaster.getMinY();
Object tdata = null;
for (int startY=0; startY < height; startY++) {
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
width, 1, tdata);
setDataElements(dstOffX, dstOffY+startY,
width, 1, tdata);
}
}
/**
* Sets the data for a rectangle of pixels from a
* primitive array of type TransferType. For image data supported by
* the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
* DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
* DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
* may be in a packed format, thus increasing efficiency for data
* transfers.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if inData is not large enough to hold the pixel data.
* However, explicit bounds checking is not guaranteed.
* A ClassCastException will be thrown if the input object is not null
* and references anything other than an array of TransferType.
* @see java.awt.image.SampleModel#setDataElements(int, int, int, int, Object, DataBuffer)
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param inData An object reference to an array of type defined by
* getTransferType() and length w*h*getNumDataElements()
* containing the pixel data to place between x,y and
* x+w-1, y+h-1.
*
* @throws NullPointerException if inData is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if inData is too small to hold the input.
*/
public void setDataElements(int x, int y, int w, int h, Object inData) {
sampleModel.setDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w,h,inData,dataBuffer);
}
/**
* Copies pixels from Raster srcRaster to this WritableRaster. Each pixel
* in srcRaster is copied to the same x,y address in this raster, unless
* the address falls outside the bounds of this raster. srcRaster
* must have the same number of bands as this WritableRaster. The
* copy is a simple copy of source samples to the corresponding destination
* samples.
* <p>
* If all samples of both source and destination Rasters are of
* integral type and less than or equal to 32 bits in size, then calling
* this method is equivalent to executing the following code for all
* <code>x,y</code> addresses valid in both Rasters.
* <pre>{@code
* Raster srcRaster;
* WritableRaster dstRaster;
* for (int b = 0; b < srcRaster.getNumBands(); b++) {
* dstRaster.setSample(x, y, b, srcRaster.getSample(x, y, b));
* }
* }</pre>
* Thus, when copying an integral type source to an integral type
* destination, if the source sample size is greater than the destination
* sample size for a particular band, the high order bits of the source
* sample are truncated. If the source sample size is less than the
* destination size for a particular band, the high order bits of the
* destination are zero-extended or sign-extended depending on whether
* srcRaster's SampleModel treats the sample as a signed or unsigned
* quantity.
* <p>
* When copying a float or double source to an integral type destination,
* each source sample is cast to the destination type. When copying an
* integral type source to a float or double destination, the source
* is first converted to a 32-bit int (if necessary), using the above
* rules for integral types, and then the int is cast to float or
* double.
* <p>
* @param srcRaster The Raster from which to copy pixels.
*
* @throws NullPointerException if srcRaster is null.
*/
public void setRect(Raster srcRaster) {
setRect(0,0,srcRaster);
}
/**
* Copies pixels from Raster srcRaster to this WritableRaster.
* For each (x, y) address in srcRaster, the corresponding pixel
* is copied to address (x+dx, y+dy) in this WritableRaster,
* unless (x+dx, y+dy) falls outside the bounds of this raster.
* srcRaster must have the same number of bands as this WritableRaster.
* The copy is a simple copy of source samples to the corresponding
* destination samples. For details, see
* {@link WritableRaster#setRect(Raster)}.
*
* @param dx The X translation factor from src space to dst space
* of the copy.
* @param dy The Y translation factor from src space to dst space
* of the copy.
* @param srcRaster The Raster from which to copy pixels.
*
* @throws NullPointerException if srcRaster is null.
*/
public void setRect(int dx, int dy, Raster srcRaster) {
int width = srcRaster.getWidth();
int height = srcRaster.getHeight();
int srcOffX = srcRaster.getMinX();
int srcOffY = srcRaster.getMinY();
int dstOffX = dx+srcOffX;
int dstOffY = dy+srcOffY;
// Clip to this raster
if (dstOffX < this.minX) {
int skipX = this.minX - dstOffX;
width -= skipX;
srcOffX += skipX;
dstOffX = this.minX;
}
if (dstOffY < this.minY) {
int skipY = this.minY - dstOffY;
height -= skipY;
srcOffY += skipY;
dstOffY = this.minY;
}
if (dstOffX+width > this.minX+this.width) {
width = this.minX + this.width - dstOffX;
}
if (dstOffY+height > this.minY+this.height) {
height = this.minY + this.height - dstOffY;
}
if (width <= 0 || height <= 0) {
return;
}
switch (srcRaster.getSampleModel().getDataType()) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_SHORT:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_INT:
int[] iData = null;
for (int startY=0; startY < height; startY++) {
// Grab one scanline at a time
iData =
srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
iData);
setPixels(dstOffX, dstOffY+startY, width, 1, iData);
}
break;
case DataBuffer.TYPE_FLOAT:
float[] fData = null;
for (int startY=0; startY < height; startY++) {
fData =
srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
fData);
setPixels(dstOffX, dstOffY+startY, width, 1, fData);
}
break;
case DataBuffer.TYPE_DOUBLE:
double[] dData = null;
for (int startY=0; startY < height; startY++) {
// Grab one scanline at a time
dData =
srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
dData);
setPixels(dstOffX, dstOffY+startY, width, 1, dData);
}
break;
}
}
/**
* Sets a pixel in the DataBuffer using an int array of samples for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param iArray The input samples in a int array.
*
* @throws NullPointerException if iArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if iArray is too small to hold the input.
*/
public void setPixel(int x, int y, int iArray[]) {
sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
iArray,dataBuffer);
}
/**
* Sets a pixel in the DataBuffer using a float array of samples for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param fArray The input samples in a float array.
*
* @throws NullPointerException if fArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if fArray is too small to hold the input.
*/
public void setPixel(int x, int y, float fArray[]) {
sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
fArray,dataBuffer);
}
/**
* Sets a pixel in the DataBuffer using a double array of samples for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param dArray The input samples in a double array.
*
* @throws NullPointerException if dArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if dArray is too small to hold the input.
*/
public void setPixel(int x, int y, double dArray[]) {
sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
dArray,dataBuffer);
}
/**
* Sets all samples for a rectangle of pixels from an int array containing
* one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param iArray The input int pixel array.
*
* @throws NullPointerException if iArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if iArray is too small to hold the input.
*/
public void setPixels(int x, int y, int w, int h, int iArray[]) {
sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,iArray,dataBuffer);
}
/**
* Sets all samples for a rectangle of pixels from a float array containing
* one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param fArray The input float pixel array.
*
* @throws NullPointerException if fArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if fArray is too small to hold the input.
*/
public void setPixels(int x, int y, int w, int h, float fArray[]) {
sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,fArray,dataBuffer);
}
/**
* Sets all samples for a rectangle of pixels from a double array containing
* one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param dArray The input double pixel array.
*
* @throws NullPointerException if dArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if dArray is too small to hold the input.
*/
public void setPixels(int x, int y, int w, int h, double dArray[]) {
sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,dArray,dataBuffer);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using an int for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds.
*/
public void setSample(int x, int y, int b, int s) {
sampleModel.setSample(x-sampleModelTranslateX,
y-sampleModelTranslateY, b, s,
dataBuffer);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a float for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as a float.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds.
*/
public void setSample(int x, int y, int b, float s){
sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
b,s,dataBuffer);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a double for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as a double.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds.
*/
public void setSample(int x, int y, int b, double s){
sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
b,s,dataBuffer);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from an int array containing one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param b The band to set.
* @param iArray The input int sample array.
*
* @throws NullPointerException if iArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds, or if iArray is too small to
* hold the input.
*/
public void setSamples(int x, int y, int w, int h, int b,
int iArray[]) {
sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,b,iArray,dataBuffer);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from a float array containing one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param b The band to set.
* @param fArray The input float sample array.
*
* @throws NullPointerException if fArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds, or if fArray is too small to
* hold the input.
*/
public void setSamples(int x, int y, int w, int h, int b,
float fArray[]) {
sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,b,fArray,dataBuffer);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from a double array containing one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param b The band to set.
* @param dArray The input double sample array.
*
* @throws NullPointerException if dArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds, or if dArray is too small to
* hold the input.
*/
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);
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.awt.Point;
/**
* WriteableRenderedImage is a common interface for objects which
* contain or can produce image data in the form of Rasters and
* which can be modified and/or written over. The image
* data may be stored/produced as a single tile or a regular array
* of tiles.
* <p>
* WritableRenderedImage provides notification to other interested
* objects when a tile is checked out for writing (via the
* getWritableTile method) and when the last writer of a particular
* tile relinquishes its access (via a call to releaseWritableTile).
* Additionally, it allows any caller to determine whether any tiles
* are currently checked out (via hasTileWriters), and to obtain a
* list of such tiles (via getWritableTileIndices, in the form of a Vector
* of Point objects).
* <p>
* Objects wishing to be notified of changes in tile writability must
* implement the TileObserver interface, and are added by a
* call to addTileObserver. Multiple calls to
* addTileObserver for the same object will result in multiple
* notifications. An existing observer may reduce its notifications
* by calling removeTileObserver; if the observer had no
* notifications the operation is a no-op.
* <p>
* It is necessary for a WritableRenderedImage to ensure that
* notifications occur only when the first writer acquires a tile and
* the last writer releases it.
*
*/
public interface WritableRenderedImage extends RenderedImage
{
/**
* Adds an observer. If the observer is already present,
* it will receive multiple notifications.
* @param to the specified <code>TileObserver</code>
*/
public void addTileObserver(TileObserver to);
/**
* Removes an observer. If the observer was not registered,
* nothing happens. If the observer was registered for multiple
* notifications, it will now be registered for one fewer.
* @param to the specified <code>TileObserver</code>
*/
public void removeTileObserver(TileObserver to);
/**
* Checks out a tile for writing.
*
* The WritableRenderedImage is responsible for notifying all
* of its TileObservers when a tile goes from having
* no writers to having one writer.
*
* @param tileX the X index of the tile.
* @param tileY the Y index of the tile.
* @return a writable tile.
*/
public WritableRaster getWritableTile(int tileX, int tileY);
/**
* Relinquishes the right to write to a tile. If the caller
* continues to write to the tile, the results are undefined.
* Calls to this method should only appear in matching pairs
* with calls to getWritableTile; any other use will lead
* to undefined results.
*
* The WritableRenderedImage is responsible for notifying all of
* its TileObservers when a tile goes from having one writer
* to having no writers.
*
* @param tileX the X index of the tile.
* @param tileY the Y index of the tile.
*/
public void releaseWritableTile(int tileX, int tileY);
/**
* Returns whether a tile is currently checked out for writing.
*
* @param tileX the X index of the tile.
* @param tileY the Y index of the tile.
* @return <code>true</code> if specified tile is checked out
* for writing; <code>false</code> otherwise.
*/
public boolean isTileWritable(int tileX, int tileY);
/**
* Returns an array of Point objects indicating which tiles
* are checked out for writing. Returns null if none are
* checked out.
* @return an array containing the locations of tiles that are
* checked out for writing.
*/
public Point[] getWritableTileIndices();
/**
* Returns whether any tile is checked out for writing.
* Semantically equivalent to (getWritableTileIndices() != null).
* @return <code>true</code> if any tiles are checked out for
* writing; <code>false</code> otherwise.
*/
public boolean hasTileWriters();
/**
* Sets a rect of the image to the contents of the Raster r, which is
* assumed to be in the same coordinate space as the WritableRenderedImage.
* The operation is clipped to the bounds of the WritableRenderedImage.
* @param r the specified <code>Raster</code>
*/
public void setData(Raster r);
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
/**
* ContextualRenderedImageFactory provides an interface for the
* functionality that may differ between instances of
* RenderableImageOp. Thus different operations on RenderableImages
* may be performed by a single class such as RenderedImageOp through
* the use of multiple instances of ContextualRenderedImageFactory.
* The name ContextualRenderedImageFactory is commonly shortened to
* "CRIF."
*
* <p> All operations that are to be used in a rendering-independent
* chain must implement ContextualRenderedImageFactory.
*
* <p> Classes that implement this interface must provide a
* constructor with no arguments.
*/
public interface ContextualRenderedImageFactory extends RenderedImageFactory {
/**
* Maps the operation's output RenderContext into a RenderContext
* for each of the operation's sources. This is useful for
* operations that can be expressed in whole or in part simply as
* alterations in the RenderContext, such as an affine mapping, or
* operations that wish to obtain lower quality renderings of
* their sources in order to save processing effort or
* transmission bandwith. Some operations, such as blur, can also
* use this mechanism to avoid obtaining sources of higher quality
* than necessary.
*
* @param i the index of the source image.
* @param renderContext the RenderContext being applied to the operation.
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters.
* @param image the RenderableImage being rendered.
* @return a <code>RenderContext</code> for
* the source at the specified index of the parameters
* Vector contained in the specified ParameterBlock.
*/
RenderContext mapRenderContext(int i,
RenderContext renderContext,
ParameterBlock paramBlock,
RenderableImage image);
/**
* Creates a rendering, given a RenderContext and a ParameterBlock
* containing the operation's sources and parameters. The output
* is a RenderedImage that takes the RenderContext into account to
* determine its dimensions and placement on the image plane.
* This method houses the "intelligence" that allows a
* rendering-independent operation to adapt to a specific
* RenderContext.
*
* @param renderContext The RenderContext specifying the rendering
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters
* @return a <code>RenderedImage</code> from the sources and parameters
* in the specified ParameterBlock and according to the
* rendering instructions in the specified RenderContext.
*/
RenderedImage create(RenderContext renderContext,
ParameterBlock paramBlock);
/**
* Returns the bounding box for the output of the operation,
* performed on a given set of sources, in rendering-independent
* space. The bounds are returned as a Rectangle2D, that is, an
* axis-aligned rectangle with floating-point corner coordinates.
*
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters.
* @return a Rectangle2D specifying the rendering-independent
* bounding box of the output.
*/
Rectangle2D getBounds2D(ParameterBlock paramBlock);
/**
* Gets the appropriate instance of the property specified by the name
* parameter. This method must determine which instance of a property to
* return when there are multiple sources that each specify the property.
*
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters.
* @param name a String naming the desired property.
* @return an object reference to the value of the property requested.
*/
Object getProperty(ParameterBlock paramBlock, String name);
/**
* Returns a list of names recognized by getProperty.
* @return the list of property names.
*/
String[] getPropertyNames();
/**
* Returns true if successive renderings (that is, calls to
* create(RenderContext, ParameterBlock)) with the same arguments
* may produce different results. This method may be used to
* determine whether an existing rendering may be cached and
* reused. It is always safe to return true.
* @return <code>true</code> if successive renderings with the
* same arguments might produce different results;
* <code>false</code> otherwise.
*/
boolean isDynamic();
}

View File

@@ -0,0 +1,725 @@
/*
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image.renderable;
import java.awt.image.RenderedImage;
import java.io.Serializable;
import java.util.Vector;
/**
* A <code>ParameterBlock</code> encapsulates all the information about sources and
* parameters (Objects) required by a RenderableImageOp, or other
* classes that process images.
*
* <p> Although it is possible to place arbitrary objects in the
* source Vector, users of this class may impose semantic constraints
* such as requiring all sources to be RenderedImages or
* RenderableImage. <code>ParameterBlock</code> itself is merely a container and
* performs no checking on source or parameter types.
*
* <p> All parameters in a <code>ParameterBlock</code> are objects; convenience
* add and set methods are available that take arguments of base type and
* construct the appropriate subclass of Number (such as
* Integer or Float). Corresponding get methods perform a
* downward cast and have return values of base type; an exception
* will be thrown if the stored values do not have the correct type.
* There is no way to distinguish between the results of
* "short s; add(s)" and "add(new Short(s))".
*
* <p> Note that the get and set methods operate on references.
* Therefore, one must be careful not to share references between
* <code>ParameterBlock</code>s when this is inappropriate. For example, to create
* a new <code>ParameterBlock</code> that is equal to an old one except for an
* added source, one might be tempted to write:
*
* <pre>
* ParameterBlock addSource(ParameterBlock pb, RenderableImage im) {
* ParameterBlock pb1 = new ParameterBlock(pb.getSources());
* pb1.addSource(im);
* return pb1;
* }
* </pre>
*
* <p> This code will have the side effect of altering the original
* <code>ParameterBlock</code>, since the getSources operation returned a reference
* to its source Vector. Both pb and pb1 share their source Vector,
* and a change in either is visible to both.
*
* <p> A correct way to write the addSource function is to clone
* the source Vector:
*
* <pre>
* ParameterBlock addSource (ParameterBlock pb, RenderableImage im) {
* ParameterBlock pb1 = new ParameterBlock(pb.getSources().clone());
* pb1.addSource(im);
* return pb1;
* }
* </pre>
*
* <p> The clone method of <code>ParameterBlock</code> has been defined to
* perform a clone of both the source and parameter Vectors for
* this reason. A standard, shallow clone is available as
* shallowClone.
*
* <p> The addSource, setSource, add, and set methods are
* defined to return 'this' after adding their argument. This allows
* use of syntax like:
*
* <pre>
* ParameterBlock pb = new ParameterBlock();
* op = new RenderableImageOp("operation", pb.add(arg1).add(arg2));
* </pre>
* */
public class ParameterBlock implements Cloneable, Serializable {
/** A Vector of sources, stored as arbitrary Objects. */
protected Vector<Object> sources = new Vector<Object>();
/** A Vector of non-source parameters, stored as arbitrary Objects. */
protected Vector<Object> parameters = new Vector<Object>();
/** A dummy constructor. */
public ParameterBlock() {}
/**
* Constructs a <code>ParameterBlock</code> with a given Vector
* of sources.
* @param sources a <code>Vector</code> of source images
*/
public ParameterBlock(Vector<Object> sources) {
setSources(sources);
}
/**
* Constructs a <code>ParameterBlock</code> with a given Vector of sources and
* Vector of parameters.
* @param sources a <code>Vector</code> of source images
* @param parameters a <code>Vector</code> of parameters to be used in the
* rendering operation
*/
public ParameterBlock(Vector<Object> sources,
Vector<Object> parameters)
{
setSources(sources);
setParameters(parameters);
}
/**
* Creates a shallow copy of a <code>ParameterBlock</code>. The source and
* parameter Vectors are copied by reference -- additions or
* changes will be visible to both versions.
*
* @return an Object clone of the <code>ParameterBlock</code>.
*/
public Object shallowClone() {
try {
return super.clone();
} catch (Exception e) {
// We can't be here since we implement Cloneable.
return null;
}
}
/**
* Creates a copy of a <code>ParameterBlock</code>. The source and parameter
* Vectors are cloned, but the actual sources and parameters are
* copied by reference. This allows modifications to the order
* and number of sources and parameters in the clone to be invisible
* to the original <code>ParameterBlock</code>. Changes to the shared sources or
* parameters themselves will still be visible.
*
* @return an Object clone of the <code>ParameterBlock</code>.
*/
public Object clone() {
ParameterBlock theClone;
try {
theClone = (ParameterBlock) super.clone();
} catch (Exception e) {
// We can't be here since we implement Cloneable.
return null;
}
if (sources != null) {
theClone.setSources((Vector)sources.clone());
}
if (parameters != null) {
theClone.setParameters((Vector)parameters.clone());
}
return (Object) theClone;
}
/**
* Adds an image to end of the list of sources. The image is
* stored as an object in order to allow new node types in the
* future.
*
* @param source an image object to be stored in the source list.
* @return a new <code>ParameterBlock</code> containing the specified
* <code>source</code>.
*/
public ParameterBlock addSource(Object source) {
sources.addElement(source);
return this;
}
/**
* Returns a source as a general Object. The caller must cast it into
* an appropriate type.
*
* @param index the index of the source to be returned.
* @return an <code>Object</code> that represents the source located
* at the specified index in the <code>sources</code>
* <code>Vector</code>.
* @see #setSource(Object, int)
*/
public Object getSource(int index) {
return sources.elementAt(index);
}
/**
* Replaces an entry in the list of source with a new source.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param source the specified source image
* @param index the index into the <code>sources</code>
* <code>Vector</code> at which to
* insert the specified <code>source</code>
* @return a new <code>ParameterBlock</code> that contains the
* specified <code>source</code> at the specified
* <code>index</code>.
* @see #getSource(int)
*/
public ParameterBlock setSource(Object source, int index) {
int oldSize = sources.size();
int newSize = index + 1;
if (oldSize < newSize) {
sources.setSize(newSize);
}
sources.setElementAt(source, index);
return this;
}
/**
* Returns a source as a <code>RenderedImage</code>. This method is
* a convenience method.
* An exception will be thrown if the source is not a RenderedImage.
*
* @param index the index of the source to be returned
* @return a <code>RenderedImage</code> that represents the source
* image that is at the specified index in the
* <code>sources</code> <code>Vector</code>.
*/
public RenderedImage getRenderedSource(int index) {
return (RenderedImage) sources.elementAt(index);
}
/**
* Returns a source as a RenderableImage. This method is a
* convenience method.
* An exception will be thrown if the sources is not a RenderableImage.
*
* @param index the index of the source to be returned
* @return a <code>RenderableImage</code> that represents the source
* image that is at the specified index in the
* <code>sources</code> <code>Vector</code>.
*/
public RenderableImage getRenderableSource(int index) {
return (RenderableImage) sources.elementAt(index);
}
/**
* Returns the number of source images.
* @return the number of source images in the <code>sources</code>
* <code>Vector</code>.
*/
public int getNumSources() {
return sources.size();
}
/**
* Returns the entire Vector of sources.
* @return the <code>sources</code> <code>Vector</code>.
* @see #setSources(Vector)
*/
public Vector<Object> getSources() {
return sources;
}
/**
* Sets the entire Vector of sources to a given Vector.
* @param sources the <code>Vector</code> of source images
* @see #getSources
*/
public void setSources(Vector<Object> sources) {
this.sources = sources;
}
/** Clears the list of source images. */
public void removeSources() {
sources = new Vector();
}
/**
* Returns the number of parameters (not including source images).
* @return the number of parameters in the <code>parameters</code>
* <code>Vector</code>.
*/
public int getNumParameters() {
return parameters.size();
}
/**
* Returns the entire Vector of parameters.
* @return the <code>parameters</code> <code>Vector</code>.
* @see #setParameters(Vector)
*/
public Vector<Object> getParameters() {
return parameters;
}
/**
* Sets the entire Vector of parameters to a given Vector.
* @param parameters the specified <code>Vector</code> of
* parameters
* @see #getParameters
*/
public void setParameters(Vector<Object> parameters) {
this.parameters = parameters;
}
/** Clears the list of parameters. */
public void removeParameters() {
parameters = new Vector();
}
/**
* Adds an object to the list of parameters.
* @param obj the <code>Object</code> to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(Object obj) {
parameters.addElement(obj);
return this;
}
/**
* Adds a Byte to the list of parameters.
* @param b the byte to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(byte b) {
return add(new Byte(b));
}
/**
* Adds a Character to the list of parameters.
* @param c the char to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(char c) {
return add(new Character(c));
}
/**
* Adds a Short to the list of parameters.
* @param s the short to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(short s) {
return add(new Short(s));
}
/**
* Adds a Integer to the list of parameters.
* @param i the int to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(int i) {
return add(new Integer(i));
}
/**
* Adds a Long to the list of parameters.
* @param l the long to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(long l) {
return add(new Long(l));
}
/**
* Adds a Float to the list of parameters.
* @param f the float to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(float f) {
return add(new Float(f));
}
/**
* Adds a Double to the list of parameters.
* @param d the double to add to the
* <code>parameters</code> <code>Vector</code>
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock add(double d) {
return add(new Double(d));
}
/**
* Replaces an Object in the list of parameters.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param obj the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(Object obj, int index) {
int oldSize = parameters.size();
int newSize = index + 1;
if (oldSize < newSize) {
parameters.setSize(newSize);
}
parameters.setElementAt(obj, index);
return this;
}
/**
* Replaces an Object in the list of parameters with a Byte.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param b the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(byte b, int index) {
return set(new Byte(b), index);
}
/**
* Replaces an Object in the list of parameters with a Character.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param c the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(char c, int index) {
return set(new Character(c), index);
}
/**
* Replaces an Object in the list of parameters with a Short.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param s the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(short s, int index) {
return set(new Short(s), index);
}
/**
* Replaces an Object in the list of parameters with an Integer.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param i the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(int i, int index) {
return set(new Integer(i), index);
}
/**
* Replaces an Object in the list of parameters with a Long.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param l the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(long l, int index) {
return set(new Long(l), index);
}
/**
* Replaces an Object in the list of parameters with a Float.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param f the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(float f, int index) {
return set(new Float(f), index);
}
/**
* Replaces an Object in the list of parameters with a Double.
* If the index lies beyond the current source list,
* the list is extended with nulls as needed.
* @param d the parameter that replaces the
* parameter at the specified index in the
* <code>parameters</code> <code>Vector</code>
* @param index the index of the parameter to be
* replaced with the specified parameter
* @return a new <code>ParameterBlock</code> containing
* the specified parameter.
*/
public ParameterBlock set(double d, int index) {
return set(new Double(d), index);
}
/**
* Gets a parameter as an object.
* @param index the index of the parameter to get
* @return an <code>Object</code> representing the
* the parameter at the specified index
* into the <code>parameters</code>
* <code>Vector</code>.
*/
public Object getObjectParameter(int index) {
return parameters.elementAt(index);
}
/**
* A convenience method to return a parameter as a byte. An
* exception is thrown if the parameter is
* <code>null</code> or not a <code>Byte</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>byte</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Byte</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public byte getByteParameter(int index) {
return ((Byte)parameters.elementAt(index)).byteValue();
}
/**
* A convenience method to return a parameter as a char. An
* exception is thrown if the parameter is
* <code>null</code> or not a <code>Character</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>char</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Character</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public char getCharParameter(int index) {
return ((Character)parameters.elementAt(index)).charValue();
}
/**
* A convenience method to return a parameter as a short. An
* exception is thrown if the parameter is
* <code>null</code> or not a <code>Short</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>short</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Short</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public short getShortParameter(int index) {
return ((Short)parameters.elementAt(index)).shortValue();
}
/**
* A convenience method to return a parameter as an int. An
* exception is thrown if the parameter is
* <code>null</code> or not an <code>Integer</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>int</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Integer</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public int getIntParameter(int index) {
return ((Integer)parameters.elementAt(index)).intValue();
}
/**
* A convenience method to return a parameter as a long. An
* exception is thrown if the parameter is
* <code>null</code> or not a <code>Long</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>long</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Long</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public long getLongParameter(int index) {
return ((Long)parameters.elementAt(index)).longValue();
}
/**
* A convenience method to return a parameter as a float. An
* exception is thrown if the parameter is
* <code>null</code> or not a <code>Float</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>float</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Float</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public float getFloatParameter(int index) {
return ((Float)parameters.elementAt(index)).floatValue();
}
/**
* A convenience method to return a parameter as a double. An
* exception is thrown if the parameter is
* <code>null</code> or not a <code>Double</code>.
*
* @param index the index of the parameter to be returned.
* @return the parameter at the specified index
* as a <code>double</code> value.
* @throws ClassCastException if the parameter at the
* specified index is not a <code>Double</code>
* @throws NullPointerException if the parameter at the specified
* index is <code>null</code>
* @throws ArrayIndexOutOfBoundsException if <code>index</code>
* is negative or not less than the current size of this
* <code>ParameterBlock</code> object
*/
public double getDoubleParameter(int index) {
return ((Double)parameters.elementAt(index)).doubleValue();
}
/**
* Returns an array of Class objects describing the types
* of the parameters.
* @return an array of <code>Class</code> objects.
*/
public Class [] getParamClasses() {
int numParams = getNumParameters();
Class [] classes = new Class[numParams];
int i;
for (i = 0; i < numParams; i++) {
Object obj = getObjectParameter(i);
if (obj instanceof Byte) {
classes[i] = byte.class;
} else if (obj instanceof Character) {
classes[i] = char.class;
} else if (obj instanceof Short) {
classes[i] = short.class;
} else if (obj instanceof Integer) {
classes[i] = int.class;
} else if (obj instanceof Long) {
classes[i] = long.class;
} else if (obj instanceof Float) {
classes[i] = float.class;
} else if (obj instanceof Double) {
classes[i] = double.class;
} else {
classes[i] = obj.getClass();
}
}
return classes;
}
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.util.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.image.*;
/**
* A RenderContext encapsulates the information needed to produce a
* specific rendering from a RenderableImage. It contains the area to
* be rendered specified in rendering-independent terms, the
* resolution at which the rendering is to be performed, and hints
* used to control the rendering process.
*
* <p> Users create RenderContexts and pass them to the
* RenderableImage via the createRendering method. Most of the methods of
* RenderContexts are not meant to be used directly by applications,
* but by the RenderableImage and operator classes to which it is
* passed.
*
* <p> The AffineTransform parameter passed into and out of this class
* are cloned. The RenderingHints and Shape parameters are not
* necessarily cloneable and are therefore only reference copied.
* Altering RenderingHints or Shape instances that are in use by
* instances of RenderContext may have undesired side effects.
*/
public class RenderContext implements Cloneable {
/** Table of hints. May be null. */
RenderingHints hints;
/** Transform to convert user coordinates to device coordinates. */
AffineTransform usr2dev;
/** The area of interest. May be null. */
Shape aoi;
// Various constructors that allow different levels of
// specificity. If the Shape is missing the whole renderable area
// is assumed. If hints is missing no hints are assumed.
/**
* Constructs a RenderContext with a given transform.
* The area of interest is supplied as a Shape,
* and the rendering hints are supplied as a RenderingHints object.
*
* @param usr2dev an AffineTransform.
* @param aoi a Shape representing the area of interest.
* @param hints a RenderingHints object containing rendering hints.
*/
public RenderContext(AffineTransform usr2dev,
Shape aoi,
RenderingHints hints) {
this.hints = hints;
this.aoi = aoi;
this.usr2dev = (AffineTransform)usr2dev.clone();
}
/**
* Constructs a RenderContext with a given transform.
* The area of interest is taken to be the entire renderable area.
* No rendering hints are used.
*
* @param usr2dev an AffineTransform.
*/
public RenderContext(AffineTransform usr2dev) {
this(usr2dev, null, null);
}
/**
* Constructs a RenderContext with a given transform and rendering hints.
* The area of interest is taken to be the entire renderable area.
*
* @param usr2dev an AffineTransform.
* @param hints a RenderingHints object containing rendering hints.
*/
public RenderContext(AffineTransform usr2dev, RenderingHints hints) {
this(usr2dev, null, hints);
}
/**
* Constructs a RenderContext with a given transform and area of interest.
* The area of interest is supplied as a Shape.
* No rendering hints are used.
*
* @param usr2dev an AffineTransform.
* @param aoi a Shape representing the area of interest.
*/
public RenderContext(AffineTransform usr2dev, Shape aoi) {
this(usr2dev, aoi, null);
}
/**
* Gets the rendering hints of this <code>RenderContext</code>.
* @return a <code>RenderingHints</code> object that represents
* the rendering hints of this <code>RenderContext</code>.
* @see #setRenderingHints(RenderingHints)
*/
public RenderingHints getRenderingHints() {
return hints;
}
/**
* Sets the rendering hints of this <code>RenderContext</code>.
* @param hints a <code>RenderingHints</code> object that represents
* the rendering hints to assign to this <code>RenderContext</code>.
* @see #getRenderingHints
*/
public void setRenderingHints(RenderingHints hints) {
this.hints = hints;
}
/**
* Sets the current user-to-device AffineTransform contained
* in the RenderContext to a given transform.
*
* @param newTransform the new AffineTransform.
* @see #getTransform
*/
public void setTransform(AffineTransform newTransform) {
usr2dev = (AffineTransform)newTransform.clone();
}
/**
* Modifies the current user-to-device transform by prepending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [modTransform] x [this]
* </pre>
*
* @param modTransform the AffineTransform to prepend to the
* current usr2dev transform.
* @since 1.3
*/
public void preConcatenateTransform(AffineTransform modTransform) {
this.preConcetenateTransform(modTransform);
}
/**
* Modifies the current user-to-device transform by prepending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [modTransform] x [this]
* </pre>
* This method does the same thing as the preConcatenateTransform
* method. It is here for backward compatibility with previous releases
* which misspelled the method name.
*
* @param modTransform the AffineTransform to prepend to the
* current usr2dev transform.
* @deprecated replaced by
* <code>preConcatenateTransform(AffineTransform)</code>.
*/
@Deprecated
public void preConcetenateTransform(AffineTransform modTransform) {
usr2dev.preConcatenate(modTransform);
}
/**
* Modifies the current user-to-device transform by appending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [this] x [modTransform]
* </pre>
*
* @param modTransform the AffineTransform to append to the
* current usr2dev transform.
* @since 1.3
*/
public void concatenateTransform(AffineTransform modTransform) {
this.concetenateTransform(modTransform);
}
/**
* Modifies the current user-to-device transform by appending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [this] x [modTransform]
* </pre>
* This method does the same thing as the concatenateTransform
* method. It is here for backward compatibility with previous releases
* which misspelled the method name.
*
* @param modTransform the AffineTransform to append to the
* current usr2dev transform.
* @deprecated replaced by
* <code>concatenateTransform(AffineTransform)</code>.
*/
@Deprecated
public void concetenateTransform(AffineTransform modTransform) {
usr2dev.concatenate(modTransform);
}
/**
* Gets the current user-to-device AffineTransform.
*
* @return a reference to the current AffineTransform.
* @see #setTransform(AffineTransform)
*/
public AffineTransform getTransform() {
return (AffineTransform)usr2dev.clone();
}
/**
* Sets the current area of interest. The old area is discarded.
*
* @param newAoi The new area of interest.
* @see #getAreaOfInterest
*/
public void setAreaOfInterest(Shape newAoi) {
aoi = newAoi;
}
/**
* Gets the ares of interest currently contained in the
* RenderContext.
*
* @return a reference to the area of interest of the RenderContext,
* or null if none is specified.
* @see #setAreaOfInterest(Shape)
*/
public Shape getAreaOfInterest() {
return aoi;
}
/**
* Makes a copy of a RenderContext. The area of interest is copied
* by reference. The usr2dev AffineTransform and hints are cloned,
* while the area of interest is copied by reference.
*
* @return the new cloned RenderContext.
*/
public Object clone() {
RenderContext newRenderContext = new RenderContext(usr2dev,
aoi, hints);
return newRenderContext;
}
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.util.Vector;
import java.awt.RenderingHints;
import java.awt.image.*;
/**
* A RenderableImage is a common interface for rendering-independent
* images (a notion which subsumes resolution independence). That is,
* images which are described and have operations applied to them
* independent of any specific rendering of the image. For example, a
* RenderableImage can be rotated and cropped in
* resolution-independent terms. Then, it can be rendered for various
* specific contexts, such as a draft preview, a high-quality screen
* display, or a printer, each in an optimal fashion.
*
* <p> A RenderedImage is returned from a RenderableImage via the
* createRendering() method, which takes a RenderContext. The
* RenderContext specifies how the RenderedImage should be
* constructed. Note that it is not possible to extract pixels
* directly from a RenderableImage.
*
* <p> The createDefaultRendering() and createScaledRendering() methods are
* convenience methods that construct an appropriate RenderContext
* internally. All of the rendering methods may return a reference to a
* previously produced rendering.
*/
public interface RenderableImage {
/**
* String constant that can be used to identify a property on
* a RenderedImage obtained via the createRendering or
* createScaledRendering methods. If such a property exists,
* the value of the property will be a RenderingHints object
* specifying which hints were observed in creating the rendering.
*/
static final String HINTS_OBSERVED = "HINTS_OBSERVED";
/**
* Returns a vector of RenderableImages that are the sources of
* image data for this RenderableImage. Note that this method may
* return an empty vector, to indicate that the image has no sources,
* or null, to indicate that no information is available.
*
* @return a (possibly empty) Vector of RenderableImages, or null.
*/
Vector<RenderableImage> getSources();
/**
* Gets a property from the property set of this image.
* If the property name is not recognized, java.awt.Image.UndefinedProperty
* will be returned.
*
* @param name the name of the property to get, as a String.
* @return a reference to the property Object, or the value
* java.awt.Image.UndefinedProperty.
*/
Object getProperty(String name);
/**
* Returns a list of names recognized by getProperty.
* @return a list of property names.
*/
String[] getPropertyNames();
/**
* Returns true if successive renderings (that is, calls to
* createRendering() or createScaledRendering()) with the same arguments
* may produce different results. This method may be used to
* determine whether an existing rendering may be cached and
* reused. It is always safe to return true.
* @return <code>true</code> if successive renderings with the
* same arguments might produce different results;
* <code>false</code> otherwise.
*/
boolean isDynamic();
/**
* Gets the width in user coordinate space. By convention, the
* usual width of a RenderableImage is equal to the image's aspect
* ratio (width divided by height).
*
* @return the width of the image in user coordinates.
*/
float getWidth();
/**
* Gets the height in user coordinate space. By convention, the
* usual height of a RenderedImage is equal to 1.0F.
*
* @return the height of the image in user coordinates.
*/
float getHeight();
/**
* Gets the minimum X coordinate of the rendering-independent image data.
* @return the minimum X coordinate of the rendering-independent image
* data.
*/
float getMinX();
/**
* Gets the minimum Y coordinate of the rendering-independent image data.
* @return the minimum Y coordinate of the rendering-independent image
* data.
*/
float getMinY();
/**
* Creates a RenderedImage instance of this image with width w, and
* height h in pixels. The RenderContext is built automatically
* with an appropriate usr2dev transform and an area of interest
* of the full image. All the rendering hints come from hints
* passed in.
*
* <p> If w == 0, it will be taken to equal
* Math.round(h*(getWidth()/getHeight())).
* Similarly, if h == 0, it will be taken to equal
* Math.round(w*(getHeight()/getWidth())). One of
* w or h must be non-zero or else an IllegalArgumentException
* will be thrown.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* were used to create the image. In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param w the width of rendered image in pixels, or 0.
* @param h the height of rendered image in pixels, or 0.
* @param hints a RenderingHints object containing hints.
* @return a RenderedImage containing the rendered data.
*/
RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
/**
* Returnd a RenderedImage instance of this image with a default
* width and height in pixels. The RenderContext is built
* automatically with an appropriate usr2dev transform and an area
* of interest of the full image. The rendering hints are
* empty. createDefaultRendering may make use of a stored
* rendering for speed.
*
* @return a RenderedImage containing the rendered data.
*/
RenderedImage createDefaultRendering();
/**
* Creates a RenderedImage that represented a rendering of this image
* using a given RenderContext. This is the most general way to obtain a
* rendering of a RenderableImage.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* (from the RenderContext) were used to create the image.
* In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param renderContext the RenderContext to use to produce the rendering.
* @return a RenderedImage containing the rendered data.
*/
RenderedImage createRendering(RenderContext renderContext);
}

View File

@@ -0,0 +1,350 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.awt.RenderingHints;
import java.util.Hashtable;
import java.util.Vector;
/**
* This class handles the renderable aspects of an operation with help
* from its associated instance of a ContextualRenderedImageFactory.
*/
public class RenderableImageOp implements RenderableImage {
/** A ParameterBlock containing source and parameters. */
ParameterBlock paramBlock;
/** The associated ContextualRenderedImageFactory. */
ContextualRenderedImageFactory myCRIF;
/** The bounding box of the results of this RenderableImageOp. */
Rectangle2D boundingBox;
/**
* Constructs a RenderedImageOp given a
* ContextualRenderedImageFactory object, and
* a ParameterBlock containing RenderableImage sources and other
* parameters. Any RenderedImage sources referenced by the
* ParameterBlock will be ignored.
*
* @param CRIF a ContextualRenderedImageFactory object
* @param paramBlock a ParameterBlock containing this operation's source
* images and other parameters necessary for the operation
* to run.
*/
public RenderableImageOp(ContextualRenderedImageFactory CRIF,
ParameterBlock paramBlock) {
this.myCRIF = CRIF;
this.paramBlock = (ParameterBlock) paramBlock.clone();
}
/**
* Returns a vector of RenderableImages that are the sources of
* image data for this RenderableImage. Note that this method may
* return an empty vector, to indicate that the image has no sources,
* or null, to indicate that no information is available.
*
* @return a (possibly empty) Vector of RenderableImages, or null.
*/
public Vector<RenderableImage> getSources() {
return getRenderableSources();
}
private Vector getRenderableSources() {
Vector sources = null;
if (paramBlock.getNumSources() > 0) {
sources = new Vector();
int i = 0;
while (i < paramBlock.getNumSources()) {
Object o = paramBlock.getSource(i);
if (o instanceof RenderableImage) {
sources.add((RenderableImage)o);
i++;
} else {
break;
}
}
}
return sources;
}
/**
* Gets a property from the property set of this image.
* If the property name is not recognized, java.awt.Image.UndefinedProperty
* will be returned.
*
* @param name the name of the property to get, as a String.
* @return a reference to the property Object, or the value
* java.awt.Image.UndefinedProperty.
*/
public Object getProperty(String name) {
return myCRIF.getProperty(paramBlock, name);
}
/**
* Return a list of names recognized by getProperty.
* @return a list of property names.
*/
public String[] getPropertyNames() {
return myCRIF.getPropertyNames();
}
/**
* Returns true if successive renderings (that is, calls to
* createRendering() or createScaledRendering()) with the same arguments
* may produce different results. This method may be used to
* determine whether an existing rendering may be cached and
* reused. The CRIF's isDynamic method will be called.
* @return <code>true</code> if successive renderings with the
* same arguments might produce different results;
* <code>false</code> otherwise.
*/
public boolean isDynamic() {
return myCRIF.isDynamic();
}
/**
* Gets the width in user coordinate space. By convention, the
* usual width of a RenderableImage is equal to the image's aspect
* ratio (width divided by height).
*
* @return the width of the image in user coordinates.
*/
public float getWidth() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getWidth();
}
/**
* Gets the height in user coordinate space. By convention, the
* usual height of a RenderedImage is equal to 1.0F.
*
* @return the height of the image in user coordinates.
*/
public float getHeight() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getHeight();
}
/**
* Gets the minimum X coordinate of the rendering-independent image data.
*/
public float getMinX() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getMinX();
}
/**
* Gets the minimum Y coordinate of the rendering-independent image data.
*/
public float getMinY() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getMinY();
}
/**
* Change the current ParameterBlock of the operation, allowing
* editing of image rendering chains. The effects of such a
* change will be visible when a new rendering is created from
* this RenderableImageOp or any dependent RenderableImageOp.
*
* @param paramBlock the new ParameterBlock.
* @return the old ParameterBlock.
* @see #getParameterBlock
*/
public ParameterBlock setParameterBlock(ParameterBlock paramBlock) {
ParameterBlock oldParamBlock = this.paramBlock;
this.paramBlock = (ParameterBlock)paramBlock.clone();
return oldParamBlock;
}
/**
* Returns a reference to the current parameter block.
* @return the <code>ParameterBlock</code> of this
* <code>RenderableImageOp</code>.
* @see #setParameterBlock(ParameterBlock)
*/
public ParameterBlock getParameterBlock() {
return paramBlock;
}
/**
* Creates a RenderedImage instance of this image with width w, and
* height h in pixels. The RenderContext is built automatically
* with an appropriate usr2dev transform and an area of interest
* of the full image. All the rendering hints come from hints
* passed in.
*
* <p> If w == 0, it will be taken to equal
* Math.round(h*(getWidth()/getHeight())).
* Similarly, if h == 0, it will be taken to equal
* Math.round(w*(getHeight()/getWidth())). One of
* w or h must be non-zero or else an IllegalArgumentException
* will be thrown.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* were used to create the image. In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param w the width of rendered image in pixels, or 0.
* @param h the height of rendered image in pixels, or 0.
* @param hints a RenderingHints object containing hints.
* @return a RenderedImage containing the rendered data.
*/
public RenderedImage createScaledRendering(int w, int h,
RenderingHints hints) {
// DSR -- code to try to get a unit scale
double sx = (double)w/getWidth();
double sy = (double)h/getHeight();
if (Math.abs(sx/sy - 1.0) < 0.01) {
sx = sy;
}
AffineTransform usr2dev = AffineTransform.getScaleInstance(sx, sy);
RenderContext newRC = new RenderContext(usr2dev, hints);
return createRendering(newRC);
}
/**
* Gets a RenderedImage instance of this image with a default
* width and height in pixels. The RenderContext is built
* automatically with an appropriate usr2dev transform and an area
* of interest of the full image. All the rendering hints come
* from hints passed in. Implementors of this interface must be
* sure that there is a defined default width and height.
*
* @return a RenderedImage containing the rendered data.
*/
public RenderedImage createDefaultRendering() {
AffineTransform usr2dev = new AffineTransform(); // Identity
RenderContext newRC = new RenderContext(usr2dev);
return createRendering(newRC);
}
/**
* Creates a RenderedImage which represents this
* RenderableImageOp (including its Renderable sources) rendered
* according to the given RenderContext.
*
* <p> This method supports chaining of either Renderable or
* RenderedImage operations. If sources in
* the ParameterBlock used to construct the RenderableImageOp are
* RenderableImages, then a three step process is followed:
*
* <ol>
* <li> mapRenderContext() is called on the associated CRIF for
* each RenderableImage source;
* <li> createRendering() is called on each of the RenderableImage sources
* using the backwards-mapped RenderContexts obtained in step 1,
* resulting in a rendering of each source;
* <li> ContextualRenderedImageFactory.create() is called
* with a new ParameterBlock containing the parameters of
* the RenderableImageOp and the RenderedImages that were created by the
* createRendering() calls.
* </ol>
*
* <p> If the elements of the source Vector of
* the ParameterBlock used to construct the RenderableImageOp are
* instances of RenderedImage, then the CRIF.create() method is
* called immediately using the original ParameterBlock.
* This provides a basis case for the recursion.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* (from the RenderContext) were used to create the image.
* In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param renderContext The RenderContext to use to perform the rendering.
* @return a RenderedImage containing the desired output image.
*/
public RenderedImage createRendering(RenderContext renderContext) {
RenderedImage image = null;
RenderContext rcOut = null;
// Clone the original ParameterBlock; if the ParameterBlock
// contains RenderableImage sources, they will be replaced by
// RenderedImages.
ParameterBlock renderedParamBlock = (ParameterBlock)paramBlock.clone();
Vector sources = getRenderableSources();
try {
// This assumes that if there is no renderable source, that there
// is a rendered source in paramBlock
if (sources != null) {
Vector renderedSources = new Vector();
for (int i = 0; i < sources.size(); i++) {
rcOut = myCRIF.mapRenderContext(i, renderContext,
paramBlock, this);
RenderedImage rdrdImage =
((RenderableImage)sources.elementAt(i)).createRendering(rcOut);
if (rdrdImage == null) {
return null;
}
// Add this rendered image to the ParameterBlock's
// list of RenderedImages.
renderedSources.addElement(rdrdImage);
}
if (renderedSources.size() > 0) {
renderedParamBlock.setSources(renderedSources);
}
}
return myCRIF.create(renderContext, renderedParamBlock);
} catch (ArrayIndexOutOfBoundsException e) {
// This should never happen
return null;
}
}
}

View File

@@ -0,0 +1,219 @@
/*
* Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.util.Enumeration;
import java.util.Vector;
/**
* An adapter class that implements ImageProducer to allow the
* asynchronous production of a RenderableImage. The size of the
* ImageConsumer is determined by the scale factor of the usr2dev
* transform in the RenderContext. If the RenderContext is null, the
* default rendering of the RenderableImage is used. This class
* implements an asynchronous production that produces the image in
* one thread at one resolution. This class may be subclassed to
* implement versions that will render the image using several
* threads. These threads could render either the same image at
* progressively better quality, or different sections of the image at
* a single resolution.
*/
public class RenderableImageProducer implements ImageProducer, Runnable {
/** The RenderableImage source for the producer. */
RenderableImage rdblImage;
/** The RenderContext to use for producing the image. */
RenderContext rc;
/** A Vector of image consumers. */
Vector ics = new Vector();
/**
* Constructs a new RenderableImageProducer from a RenderableImage
* and a RenderContext.
*
* @param rdblImage the RenderableImage to be rendered.
* @param rc the RenderContext to use for producing the pixels.
*/
public RenderableImageProducer(RenderableImage rdblImage,
RenderContext rc) {
this.rdblImage = rdblImage;
this.rc = rc;
}
/**
* Sets a new RenderContext to use for the next startProduction() call.
*
* @param rc the new RenderContext.
*/
public synchronized void setRenderContext(RenderContext rc) {
this.rc = rc;
}
/**
* Adds an ImageConsumer to the list of consumers interested in
* data for this image.
*
* @param ic an ImageConsumer to be added to the interest list.
*/
public synchronized void addConsumer(ImageConsumer ic) {
if (!ics.contains(ic)) {
ics.addElement(ic);
}
}
/**
* Determine if an ImageConsumer is on the list of consumers
* currently interested in data for this image.
*
* @param ic the ImageConsumer to be checked.
* @return true if the ImageConsumer is on the list; false otherwise.
*/
public synchronized boolean isConsumer(ImageConsumer ic) {
return ics.contains(ic);
}
/**
* Remove an ImageConsumer from the list of consumers interested in
* data for this image.
*
* @param ic the ImageConsumer to be removed.
*/
public synchronized void removeConsumer(ImageConsumer ic) {
ics.removeElement(ic);
}
/**
* Adds an ImageConsumer to the list of consumers interested in
* data for this image, and immediately starts delivery of the
* image data through the ImageConsumer interface.
*
* @param ic the ImageConsumer to be added to the list of consumers.
*/
public synchronized void startProduction(ImageConsumer ic) {
addConsumer(ic);
// Need to build a runnable object for the Thread.
Thread thread = new Thread(this, "RenderableImageProducer Thread");
thread.start();
}
/**
* Requests that a given ImageConsumer have the image data delivered
* one more time in top-down, left-right order.
*
* @param ic the ImageConsumer requesting the resend.
*/
public void requestTopDownLeftRightResend(ImageConsumer ic) {
// So far, all pixels are already sent in TDLR order
}
/**
* The runnable method for this class. This will produce an image using
* the current RenderableImage and RenderContext and send it to all the
* ImageConsumer currently registered with this class.
*/
public void run() {
// First get the rendered image
RenderedImage rdrdImage;
if (rc != null) {
rdrdImage = rdblImage.createRendering(rc);
} else {
rdrdImage = rdblImage.createDefaultRendering();
}
// And its ColorModel
ColorModel colorModel = rdrdImage.getColorModel();
Raster raster = rdrdImage.getData();
SampleModel sampleModel = raster.getSampleModel();
DataBuffer dataBuffer = raster.getDataBuffer();
if (colorModel == null) {
colorModel = ColorModel.getRGBdefault();
}
int minX = raster.getMinX();
int minY = raster.getMinY();
int width = raster.getWidth();
int height = raster.getHeight();
Enumeration icList;
ImageConsumer ic;
// Set up the ImageConsumers
icList = ics.elements();
while (icList.hasMoreElements()) {
ic = (ImageConsumer)icList.nextElement();
ic.setDimensions(width,height);
ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
ImageConsumer.COMPLETESCANLINES |
ImageConsumer.SINGLEPASS |
ImageConsumer.SINGLEFRAME);
}
// Get RGB pixels from the raster scanline by scanline and
// send to consumers.
int pix[] = new int[width];
int i,j;
int numBands = sampleModel.getNumBands();
int tmpPixel[] = new int[numBands];
for (j = 0; j < height; j++) {
for(i = 0; i < width; i++) {
sampleModel.getPixel(i, j, tmpPixel, dataBuffer);
pix[i] = colorModel.getDataElement(tmpPixel, 0);
}
// Now send the scanline to the Consumers
icList = ics.elements();
while (icList.hasMoreElements()) {
ic = (ImageConsumer)icList.nextElement();
ic.setPixels(0, j, width, 1, colorModel, pix, 0, width);
}
}
// Now tell the consumers we're done.
icList = ics.elements();
while (icList.hasMoreElements()) {
ic = (ImageConsumer)icList.nextElement();
ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.image.RenderedImage;
import java.awt.RenderingHints;
/**
* The RenderedImageFactory interface (often abbreviated RIF) is
* intended to be implemented by classes that wish to act as factories
* to produce different renderings, for example by executing a series
* of BufferedImageOps on a set of sources, depending on a specific
* set of parameters, properties, and rendering hints.
*/
public interface RenderedImageFactory {
/**
* Creates a RenderedImage representing the results of an imaging
* operation (or chain of operations) for a given ParameterBlock and
* RenderingHints. The RIF may also query any source images
* referenced by the ParameterBlock for their dimensions,
* SampleModels, properties, etc., as necessary.
*
* <p> The create() method can return null if the
* RenderedImageFactory is not capable of producing output for the
* given set of source images and parameters. For example, if a
* RenderedImageFactory is only capable of performing a 3x3
* convolution on single-banded image data, and the source image has
* multiple bands or the convolution Kernel is 5x5, null should be
* returned.
*
* <p> Hints should be taken into account, but can be ignored.
* The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* were used to create the image. In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param paramBlock a ParameterBlock containing sources and parameters
* for the RenderedImage to be created.
* @param hints a RenderingHints object containing hints.
* @return A RenderedImage containing the desired output.
*/
RenderedImage create(ParameterBlock paramBlock,
RenderingHints hints);
}