feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
122
jdkSrc/jdk8/sun/awt/image/AbstractMultiResolutionImage.java
Normal file
122
jdkSrc/jdk8/sun/awt/image/AbstractMultiResolutionImage.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* This class provides default implementations for the
|
||||
* <code>MultiResolutionImage</code> interface. The developer needs only
|
||||
* to subclass this abstract class and define the <code>getResolutionVariant</code>,
|
||||
* <code>getResolutionVariants</code>, and <code>getBaseImage</code> methods.
|
||||
*
|
||||
*
|
||||
* For example,
|
||||
* {@code
|
||||
* public class CustomMultiResolutionImage extends AbstractMultiResolutionImage {
|
||||
*
|
||||
* int baseImageIndex;
|
||||
* Image[] resolutionVariants;
|
||||
*
|
||||
* public CustomMultiResolutionImage(int baseImageIndex,
|
||||
* Image... resolutionVariants) {
|
||||
* this.baseImageIndex = baseImageIndex;
|
||||
* this.resolutionVariants = resolutionVariants;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public Image getResolutionVariant(float logicalDPIX, float logicalDPIY,
|
||||
* float baseImageWidth, float baseImageHeight,
|
||||
* float destImageWidth, float destImageHeight) {
|
||||
* // return a resolution variant based on the given logical DPI,
|
||||
* // base image size, or destination image size
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public List<Image> getResolutionVariants() {
|
||||
* return Arrays.asList(resolutionVariants);
|
||||
* }
|
||||
*
|
||||
* protected Image getBaseImage() {
|
||||
* return resolutionVariants[baseImageIndex];
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @see java.awt.Image
|
||||
* @see java.awt.image.MultiResolutionImage
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractMultiResolutionImage extends java.awt.Image
|
||||
implements MultiResolutionImage {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int getWidth(ImageObserver observer) {
|
||||
return getBaseImage().getWidth(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int getHeight(ImageObserver observer) {
|
||||
return getBaseImage().getHeight(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public ImageProducer getSource() {
|
||||
return getBaseImage().getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Graphics getGraphics() {
|
||||
return getBaseImage().getGraphics();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object getProperty(String name, ImageObserver observer) {
|
||||
return getBaseImage().getProperty(name, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return base image
|
||||
*/
|
||||
protected abstract Image getBaseImage();
|
||||
}
|
||||
31
jdkSrc/jdk8/sun/awt/image/BadDepthException.java
Normal file
31
jdkSrc/jdk8/sun/awt/image/BadDepthException.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 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 sun.awt.image;
|
||||
|
||||
public class BadDepthException extends Exception {
|
||||
public BadDepthException() {
|
||||
}
|
||||
}
|
||||
422
jdkSrc/jdk8/sun/awt/image/BufImgSurfaceData.java
Normal file
422
jdkSrc/jdk8/sun/awt/image/BufImgSurfaceData.java
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.RenderLoops;
|
||||
|
||||
|
||||
public class BufImgSurfaceData extends SurfaceData {
|
||||
BufferedImage bufImg;
|
||||
private BufferedImageGraphicsConfig graphicsConfig;
|
||||
RenderLoops solidloops;
|
||||
|
||||
private static native void initIDs(Class ICM, Class ICMColorData);
|
||||
|
||||
private static final int DCM_RGBX_RED_MASK = 0xff000000;
|
||||
private static final int DCM_RGBX_GREEN_MASK = 0x00ff0000;
|
||||
private static final int DCM_RGBX_BLUE_MASK = 0x0000ff00;
|
||||
private static final int DCM_555X_RED_MASK = 0xF800;
|
||||
private static final int DCM_555X_GREEN_MASK = 0x07C0;
|
||||
private static final int DCM_555X_BLUE_MASK = 0x003E;
|
||||
private static final int DCM_4444_RED_MASK = 0x0f00;
|
||||
private static final int DCM_4444_GREEN_MASK = 0x00f0;
|
||||
private static final int DCM_4444_BLUE_MASK = 0x000f;
|
||||
private static final int DCM_4444_ALPHA_MASK = 0xf000;
|
||||
private static final int DCM_ARGBBM_ALPHA_MASK = 0x01000000;
|
||||
private static final int DCM_ARGBBM_RED_MASK = 0x00ff0000;
|
||||
private static final int DCM_ARGBBM_GREEN_MASK = 0x0000ff00;
|
||||
private static final int DCM_ARGBBM_BLUE_MASK = 0x000000ff;
|
||||
|
||||
static {
|
||||
initIDs(IndexColorModel.class, ICMColorData.class);
|
||||
}
|
||||
|
||||
public static SurfaceData createData(BufferedImage bufImg) {
|
||||
if (bufImg == null) {
|
||||
throw new NullPointerException("BufferedImage cannot be null");
|
||||
}
|
||||
SurfaceData sData;
|
||||
ColorModel cm = bufImg.getColorModel();
|
||||
int type = bufImg.getType();
|
||||
// REMIND: Check the image type and pick an appropriate subclass
|
||||
switch (type) {
|
||||
case BufferedImage.TYPE_INT_BGR:
|
||||
sData = createDataIC(bufImg, SurfaceType.IntBgr);
|
||||
break;
|
||||
case BufferedImage.TYPE_INT_RGB:
|
||||
sData = createDataIC(bufImg, SurfaceType.IntRgb);
|
||||
break;
|
||||
case BufferedImage.TYPE_INT_ARGB:
|
||||
sData = createDataIC(bufImg, SurfaceType.IntArgb);
|
||||
break;
|
||||
case BufferedImage.TYPE_INT_ARGB_PRE:
|
||||
sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
|
||||
break;
|
||||
case BufferedImage.TYPE_3BYTE_BGR:
|
||||
sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
|
||||
break;
|
||||
case BufferedImage.TYPE_4BYTE_ABGR:
|
||||
sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
|
||||
break;
|
||||
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
|
||||
sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
|
||||
break;
|
||||
case BufferedImage.TYPE_USHORT_565_RGB:
|
||||
sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
|
||||
break;
|
||||
case BufferedImage.TYPE_USHORT_555_RGB:
|
||||
sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
|
||||
break;
|
||||
case BufferedImage.TYPE_BYTE_INDEXED:
|
||||
{
|
||||
SurfaceType sType;
|
||||
switch (cm.getTransparency()) {
|
||||
case OPAQUE:
|
||||
if (isOpaqueGray((IndexColorModel)cm)) {
|
||||
sType = SurfaceType.Index8Gray;
|
||||
} else {
|
||||
sType = SurfaceType.ByteIndexedOpaque;
|
||||
}
|
||||
break;
|
||||
case BITMASK:
|
||||
sType = SurfaceType.ByteIndexedBm;
|
||||
break;
|
||||
case TRANSLUCENT:
|
||||
sType = SurfaceType.ByteIndexed;
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Unrecognized transparency");
|
||||
}
|
||||
sData = createDataBC(bufImg, sType, 0);
|
||||
}
|
||||
break;
|
||||
case BufferedImage.TYPE_BYTE_GRAY:
|
||||
sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
|
||||
break;
|
||||
case BufferedImage.TYPE_USHORT_GRAY:
|
||||
sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
|
||||
break;
|
||||
case BufferedImage.TYPE_BYTE_BINARY:
|
||||
{
|
||||
SurfaceType sType;
|
||||
SampleModel sm = bufImg.getRaster().getSampleModel();
|
||||
switch (sm.getSampleSize(0)) {
|
||||
case 1:
|
||||
sType = SurfaceType.ByteBinary1Bit;
|
||||
break;
|
||||
case 2:
|
||||
sType = SurfaceType.ByteBinary2Bit;
|
||||
break;
|
||||
case 4:
|
||||
sType = SurfaceType.ByteBinary4Bit;
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Unrecognized pixel size");
|
||||
}
|
||||
sData = createDataBP(bufImg, sType);
|
||||
}
|
||||
break;
|
||||
case BufferedImage.TYPE_CUSTOM:
|
||||
default:
|
||||
{
|
||||
Raster raster = bufImg.getRaster();
|
||||
int numBands = raster.getNumBands();
|
||||
if (raster instanceof IntegerComponentRaster &&
|
||||
raster.getNumDataElements() == 1 &&
|
||||
((IntegerComponentRaster)raster).getPixelStride() == 1)
|
||||
{
|
||||
SurfaceType sType = SurfaceType.AnyInt;
|
||||
if (cm instanceof DirectColorModel) {
|
||||
DirectColorModel dcm = (DirectColorModel) cm;
|
||||
int aMask = dcm.getAlphaMask();
|
||||
int rMask = dcm.getRedMask();
|
||||
int gMask = dcm.getGreenMask();
|
||||
int bMask = dcm.getBlueMask();
|
||||
if (numBands == 3 &&
|
||||
aMask == 0 &&
|
||||
rMask == DCM_RGBX_RED_MASK &&
|
||||
gMask == DCM_RGBX_GREEN_MASK &&
|
||||
bMask == DCM_RGBX_BLUE_MASK)
|
||||
{
|
||||
sType = SurfaceType.IntRgbx;
|
||||
} else if (numBands == 4 &&
|
||||
aMask == DCM_ARGBBM_ALPHA_MASK &&
|
||||
rMask == DCM_ARGBBM_RED_MASK &&
|
||||
gMask == DCM_ARGBBM_GREEN_MASK &&
|
||||
bMask == DCM_ARGBBM_BLUE_MASK)
|
||||
{
|
||||
sType = SurfaceType.IntArgbBm;
|
||||
} else {
|
||||
sType = SurfaceType.AnyDcm;
|
||||
}
|
||||
}
|
||||
sData = createDataIC(bufImg, sType);
|
||||
break;
|
||||
} else if (raster instanceof ShortComponentRaster &&
|
||||
raster.getNumDataElements() == 1 &&
|
||||
((ShortComponentRaster)raster).getPixelStride() == 1)
|
||||
{
|
||||
SurfaceType sType = SurfaceType.AnyShort;
|
||||
IndexColorModel icm = null;
|
||||
if (cm instanceof DirectColorModel) {
|
||||
DirectColorModel dcm = (DirectColorModel) cm;
|
||||
int aMask = dcm.getAlphaMask();
|
||||
int rMask = dcm.getRedMask();
|
||||
int gMask = dcm.getGreenMask();
|
||||
int bMask = dcm.getBlueMask();
|
||||
if (numBands == 3 &&
|
||||
aMask == 0 &&
|
||||
rMask == DCM_555X_RED_MASK &&
|
||||
gMask == DCM_555X_GREEN_MASK &&
|
||||
bMask == DCM_555X_BLUE_MASK)
|
||||
{
|
||||
sType = SurfaceType.Ushort555Rgbx;
|
||||
} else
|
||||
if (numBands == 4 &&
|
||||
aMask == DCM_4444_ALPHA_MASK &&
|
||||
rMask == DCM_4444_RED_MASK &&
|
||||
gMask == DCM_4444_GREEN_MASK &&
|
||||
bMask == DCM_4444_BLUE_MASK)
|
||||
{
|
||||
sType = SurfaceType.Ushort4444Argb;
|
||||
}
|
||||
} else if (cm instanceof IndexColorModel) {
|
||||
icm = (IndexColorModel)cm;
|
||||
if (icm.getPixelSize() == 12) {
|
||||
if (isOpaqueGray(icm)) {
|
||||
sType = SurfaceType.Index12Gray;
|
||||
} else {
|
||||
sType = SurfaceType.UshortIndexed;
|
||||
}
|
||||
} else {
|
||||
icm = null;
|
||||
}
|
||||
}
|
||||
sData = createDataSC(bufImg, sType, icm);
|
||||
break;
|
||||
}
|
||||
sData = new BufImgSurfaceData(raster.getDataBuffer(),
|
||||
bufImg, SurfaceType.Custom);
|
||||
}
|
||||
break;
|
||||
}
|
||||
((BufImgSurfaceData) sData).initSolidLoops();
|
||||
return sData;
|
||||
}
|
||||
|
||||
public static SurfaceData createData(Raster ras, ColorModel cm) {
|
||||
throw new InternalError("SurfaceData not implemented for Raster/CM");
|
||||
}
|
||||
|
||||
public static SurfaceData createDataIC(BufferedImage bImg,
|
||||
SurfaceType sType) {
|
||||
IntegerComponentRaster icRaster =
|
||||
(IntegerComponentRaster)bImg.getRaster();
|
||||
BufImgSurfaceData bisd =
|
||||
new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType);
|
||||
bisd.initRaster(icRaster.getDataStorage(),
|
||||
icRaster.getDataOffset(0) * 4, 0,
|
||||
icRaster.getWidth(),
|
||||
icRaster.getHeight(),
|
||||
icRaster.getPixelStride() * 4,
|
||||
icRaster.getScanlineStride() * 4,
|
||||
null);
|
||||
return bisd;
|
||||
}
|
||||
|
||||
public static SurfaceData createDataSC(BufferedImage bImg,
|
||||
SurfaceType sType,
|
||||
IndexColorModel icm) {
|
||||
ShortComponentRaster scRaster =
|
||||
(ShortComponentRaster)bImg.getRaster();
|
||||
BufImgSurfaceData bisd =
|
||||
new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType);
|
||||
bisd.initRaster(scRaster.getDataStorage(),
|
||||
scRaster.getDataOffset(0) * 2, 0,
|
||||
scRaster.getWidth(),
|
||||
scRaster.getHeight(),
|
||||
scRaster.getPixelStride() * 2,
|
||||
scRaster.getScanlineStride() * 2,
|
||||
icm);
|
||||
return bisd;
|
||||
}
|
||||
|
||||
public static SurfaceData createDataBC(BufferedImage bImg,
|
||||
SurfaceType sType,
|
||||
int primaryBank) {
|
||||
ByteComponentRaster bcRaster =
|
||||
(ByteComponentRaster)bImg.getRaster();
|
||||
BufImgSurfaceData bisd =
|
||||
new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType);
|
||||
ColorModel cm = bImg.getColorModel();
|
||||
IndexColorModel icm = ((cm instanceof IndexColorModel)
|
||||
? (IndexColorModel) cm
|
||||
: null);
|
||||
bisd.initRaster(bcRaster.getDataStorage(),
|
||||
bcRaster.getDataOffset(primaryBank), 0,
|
||||
bcRaster.getWidth(),
|
||||
bcRaster.getHeight(),
|
||||
bcRaster.getPixelStride(),
|
||||
bcRaster.getScanlineStride(),
|
||||
icm);
|
||||
return bisd;
|
||||
}
|
||||
|
||||
public static SurfaceData createDataBP(BufferedImage bImg,
|
||||
SurfaceType sType) {
|
||||
BytePackedRaster bpRaster =
|
||||
(BytePackedRaster)bImg.getRaster();
|
||||
BufImgSurfaceData bisd =
|
||||
new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType);
|
||||
ColorModel cm = bImg.getColorModel();
|
||||
IndexColorModel icm = ((cm instanceof IndexColorModel)
|
||||
? (IndexColorModel) cm
|
||||
: null);
|
||||
bisd.initRaster(bpRaster.getDataStorage(),
|
||||
bpRaster.getDataBitOffset() / 8,
|
||||
bpRaster.getDataBitOffset() & 7,
|
||||
bpRaster.getWidth(),
|
||||
bpRaster.getHeight(),
|
||||
0,
|
||||
bpRaster.getScanlineStride(),
|
||||
icm);
|
||||
return bisd;
|
||||
}
|
||||
|
||||
public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
|
||||
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
|
||||
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY)
|
||||
{
|
||||
return solidloops;
|
||||
}
|
||||
return super.getRenderLoops(sg2d);
|
||||
}
|
||||
|
||||
public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
|
||||
return bufImg.getRaster();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the native Ops pointer.
|
||||
*/
|
||||
protected native void initRaster(Object theArray,
|
||||
int offset,
|
||||
int bitoffset,
|
||||
int width,
|
||||
int height,
|
||||
int pixStr,
|
||||
int scanStr,
|
||||
IndexColorModel icm);
|
||||
|
||||
public BufImgSurfaceData(DataBuffer db,
|
||||
BufferedImage bufImg, SurfaceType sType)
|
||||
{
|
||||
super(SunWritableRaster.stealTrackable(db),
|
||||
sType, bufImg.getColorModel());
|
||||
this.bufImg = bufImg;
|
||||
}
|
||||
|
||||
protected BufImgSurfaceData(SurfaceType surfaceType, ColorModel cm) {
|
||||
super(surfaceType, cm);
|
||||
}
|
||||
|
||||
public void initSolidLoops() {
|
||||
this.solidloops = getSolidLoops(getSurfaceType());
|
||||
}
|
||||
|
||||
private static final int CACHE_SIZE = 5;
|
||||
private static RenderLoops loopcache[] = new RenderLoops[CACHE_SIZE];
|
||||
private static SurfaceType typecache[] = new SurfaceType[CACHE_SIZE];
|
||||
public static synchronized RenderLoops getSolidLoops(SurfaceType type) {
|
||||
for (int i = CACHE_SIZE - 1; i >= 0; i--) {
|
||||
SurfaceType t = typecache[i];
|
||||
if (t == type) {
|
||||
return loopcache[i];
|
||||
} else if (t == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
RenderLoops l = makeRenderLoops(SurfaceType.OpaqueColor,
|
||||
CompositeType.SrcNoEa,
|
||||
type);
|
||||
System.arraycopy(loopcache, 1, loopcache, 0, CACHE_SIZE-1);
|
||||
System.arraycopy(typecache, 1, typecache, 0, CACHE_SIZE-1);
|
||||
loopcache[CACHE_SIZE - 1] = l;
|
||||
typecache[CACHE_SIZE - 1] = type;
|
||||
return l;
|
||||
}
|
||||
|
||||
public SurfaceData getReplacement() {
|
||||
// BufImgSurfaceData objects should never lose their contents,
|
||||
// so this method should never be called.
|
||||
return restoreContents(bufImg);
|
||||
}
|
||||
|
||||
public synchronized GraphicsConfiguration getDeviceConfiguration() {
|
||||
if (graphicsConfig == null) {
|
||||
graphicsConfig = BufferedImageGraphicsConfig.getConfig(bufImg);
|
||||
}
|
||||
return graphicsConfig;
|
||||
}
|
||||
|
||||
public java.awt.Rectangle getBounds() {
|
||||
return new Rectangle(bufImg.getWidth(), bufImg.getHeight());
|
||||
}
|
||||
|
||||
protected void checkCustomComposite() {
|
||||
// BufferedImages always allow Custom Composite objects since
|
||||
// their pixels are immediately retrievable anyway.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Image associated with this SurfaceData.
|
||||
*/
|
||||
public Object getDestination() {
|
||||
return bufImg;
|
||||
}
|
||||
|
||||
public static final class ICMColorData {
|
||||
private long pData = 0L;
|
||||
|
||||
private ICMColorData(long pData) {
|
||||
this.pData = pData;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
jdkSrc/jdk8/sun/awt/image/BufImgSurfaceManager.java
Normal file
69
jdkSrc/jdk8/sun/awt/image/BufImgSurfaceManager.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 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 sun.awt.image;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.image.BufferedImage;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
/**
|
||||
* This SurfaceManager variant manages the default (software) surface of a
|
||||
* BufferedImage.
|
||||
* All rendering to the image will use the software surface as the destination.
|
||||
* This is one of the more minimalist implementations of SurfaceManager.
|
||||
*/
|
||||
public class BufImgSurfaceManager extends SurfaceManager {
|
||||
/**
|
||||
* A reference to the BufferedImage whose contents are being managed.
|
||||
*/
|
||||
protected BufferedImage bImg;
|
||||
|
||||
/**
|
||||
* The default (software) surface containing the contents of the
|
||||
* BufferedImage.
|
||||
*/
|
||||
protected SurfaceData sdDefault;
|
||||
|
||||
public BufImgSurfaceManager(BufferedImage bImg) {
|
||||
this.bImg = bImg;
|
||||
this.sdDefault = BufImgSurfaceData.createData(bImg);
|
||||
}
|
||||
|
||||
public SurfaceData getPrimarySurfaceData() {
|
||||
return sdDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from platform-specific SurfaceData objects to attempt to
|
||||
* auto-restore the contents of an accelerated surface that has been lost.
|
||||
*/
|
||||
public SurfaceData restoreContents() {
|
||||
return sdDefault;
|
||||
}
|
||||
}
|
||||
68
jdkSrc/jdk8/sun/awt/image/BufImgVolatileSurfaceManager.java
Normal file
68
jdkSrc/jdk8/sun/awt/image/BufImgVolatileSurfaceManager.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 sun.awt.image;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* This SurfaceManager variant manages an unaccelerated volatile surface.
|
||||
* This class is created in the event that someone requested a VolatileImage
|
||||
* to be created from a BufferedImageGraphicsConfig, which is not platform-
|
||||
* or hardware-based, thus the resulting surface and surface manager
|
||||
* are unaccelerated. All we do in this class is implement the abstract
|
||||
* methods of VolatileSurfaceManager to return values that indicate that
|
||||
* we cannot accelerate surfaces through this SurfaceManager, thus the
|
||||
* parent class will handle things through the unaccelerated backup mechanism.
|
||||
*/
|
||||
public class BufImgVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
|
||||
/**
|
||||
* This constructor simply defers to the superclass since all of the real
|
||||
* functionality of this class is implemented in VolatileSurfaceManager.
|
||||
*/
|
||||
public BufImgVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
super(vImg, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false to indicate that this surface manager cannot accelerate
|
||||
* the image.
|
||||
*/
|
||||
protected boolean isAccelerationEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null to indicate failure in creating the accelerated surface.
|
||||
* Note that this method should not ever be called since creation of
|
||||
* accelerated surfaces should be preceded by calls to the above
|
||||
* isAccelerationEnabled() method. But we need to override this method
|
||||
* since it is abstract in our parent class.
|
||||
*/
|
||||
protected SurfaceData initAcceleratedSurface() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
81
jdkSrc/jdk8/sun/awt/image/BufferedImageDevice.java
Normal file
81
jdkSrc/jdk8/sun/awt/image/BufferedImageDevice.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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 sun.awt.image;
|
||||
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
|
||||
public class BufferedImageDevice extends GraphicsDevice
|
||||
{
|
||||
GraphicsConfiguration gc;
|
||||
|
||||
public BufferedImageDevice(BufferedImageGraphicsConfig gc) {
|
||||
this.gc = gc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this <code>GraphicsDevice</code>.
|
||||
* @return the type of this <code>GraphicsDevice</code>, which can
|
||||
* either be TYPE_RASTER_SCREEN, TYPE_PRINTER or TYPE_IMAGE_BUFFER.
|
||||
* @see #TYPE_RASTER_SCREEN
|
||||
* @see #TYPE_PRINTER
|
||||
* @see #TYPE_IMAGE_BUFFER
|
||||
*/
|
||||
public int getType() {
|
||||
return GraphicsDevice.TYPE_IMAGE_BUFFER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identification string associated with this
|
||||
* <code>GraphicsDevice</code>.
|
||||
* @return a <code>String</code> that is the identification
|
||||
* of this <code>GraphicsDevice</code>.
|
||||
*/
|
||||
public String getIDstring() {
|
||||
return ("BufferedImage");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the <code>GraphicsConfiguration</code>
|
||||
* objects associated with this <code>GraphicsDevice</code>.
|
||||
* @return an array of <code>GraphicsConfiguration</code>
|
||||
* objects that are associated with this
|
||||
* <code>GraphicsDevice</code>.
|
||||
*/
|
||||
public GraphicsConfiguration[] getConfigurations() {
|
||||
return new GraphicsConfiguration[] { gc };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default <code>GraphicsConfiguration</code>
|
||||
* associated with this <code>GraphicsDevice</code>.
|
||||
* @return the default <code>GraphicsConfiguration</code>
|
||||
* of this <code>GraphicsDevice</code>.
|
||||
*/
|
||||
public GraphicsConfiguration getDefaultConfiguration() {
|
||||
return gc;
|
||||
}
|
||||
}
|
||||
173
jdkSrc/jdk8/sun/awt/image/BufferedImageGraphicsConfig.java
Normal file
173
jdkSrc/jdk8/sun/awt/image/BufferedImageGraphicsConfig.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
public class BufferedImageGraphicsConfig
|
||||
extends GraphicsConfiguration
|
||||
{
|
||||
private static final int numconfigs = BufferedImage.TYPE_BYTE_BINARY;
|
||||
private static BufferedImageGraphicsConfig configs[] =
|
||||
new BufferedImageGraphicsConfig[numconfigs];
|
||||
|
||||
public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg) {
|
||||
BufferedImageGraphicsConfig ret;
|
||||
int type = bImg.getType();
|
||||
if (type > 0 && type < numconfigs) {
|
||||
ret = configs[type];
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = new BufferedImageGraphicsConfig(bImg, null);
|
||||
if (type > 0 && type < numconfigs) {
|
||||
configs[type] = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GraphicsDevice gd;
|
||||
ColorModel model;
|
||||
Raster raster;
|
||||
int width, height;
|
||||
|
||||
public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp) {
|
||||
if (comp == null) {
|
||||
this.gd = new BufferedImageDevice(this);
|
||||
} else {
|
||||
Graphics2D g2d = (Graphics2D)comp.getGraphics();
|
||||
this.gd = g2d.getDeviceConfiguration().getDevice();
|
||||
}
|
||||
this.model = bufImg.getColorModel();
|
||||
this.raster = bufImg.getRaster().createCompatibleWritableRaster(1, 1);
|
||||
this.width = bufImg.getWidth();
|
||||
this.height = bufImg.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the graphics device associated with this configuration.
|
||||
*/
|
||||
public GraphicsDevice getDevice() {
|
||||
return gd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BufferedImage with channel layout and color model
|
||||
* compatible with this graphics configuration. This method
|
||||
* has nothing to do with memory-mapping
|
||||
* a device. This BufferedImage has
|
||||
* a layout and color model
|
||||
* that is closest to this native device configuration and thus
|
||||
* can be optimally blitted to this device.
|
||||
*/
|
||||
public BufferedImage createCompatibleImage(int width, int height) {
|
||||
WritableRaster wr = raster.createCompatibleWritableRaster(width, height);
|
||||
return new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color model associated with this configuration.
|
||||
*/
|
||||
public ColorModel getColorModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color model associated with this configuration that
|
||||
* supports the specified transparency.
|
||||
*/
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
|
||||
if (model.getTransparency() == transparency) {
|
||||
return model;
|
||||
}
|
||||
switch (transparency) {
|
||||
case Transparency.OPAQUE:
|
||||
return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
case Transparency.BITMASK:
|
||||
return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
|
||||
case Transparency.TRANSLUCENT:
|
||||
return ColorModel.getRGBdefault();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default Transform for this configuration. This
|
||||
* Transform is typically the Identity transform for most normal
|
||||
* screens. Device coordinates for screen and printer devices will
|
||||
* have the origin in the upper left-hand corner of the target region of
|
||||
* the device, with X coordinates
|
||||
* increasing to the right and Y coordinates increasing downwards.
|
||||
* For image buffers, this Transform will be the Identity transform.
|
||||
*/
|
||||
public AffineTransform getDefaultTransform() {
|
||||
return new AffineTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a Transform that can be composed with the default Transform
|
||||
* of a Graphics2D so that 72 units in user space will equal 1 inch
|
||||
* in device space.
|
||||
* Given a Graphics2D, g, one can reset the transformation to create
|
||||
* such a mapping by using the following pseudocode:
|
||||
* <pre>
|
||||
* GraphicsConfiguration gc = g.getGraphicsConfiguration();
|
||||
*
|
||||
* g.setTransform(gc.getDefaultTransform());
|
||||
* g.transform(gc.getNormalizingTransform());
|
||||
* </pre>
|
||||
* Note that sometimes this Transform will be identity (e.g. for
|
||||
* printers or metafile output) and that this Transform is only
|
||||
* as accurate as the information supplied by the underlying system.
|
||||
* For image buffers, this Transform will be the Identity transform,
|
||||
* since there is no valid distance measurement.
|
||||
*/
|
||||
public AffineTransform getNormalizingTransform() {
|
||||
return new AffineTransform();
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
61
jdkSrc/jdk8/sun/awt/image/ByteArrayImageSource.java
Normal file
61
jdkSrc/jdk8/sun/awt/image/ByteArrayImageSource.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 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 sun.awt.image;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.BufferedInputStream;
|
||||
|
||||
public class ByteArrayImageSource extends InputStreamImageSource {
|
||||
byte[] imagedata;
|
||||
int imageoffset;
|
||||
int imagelength;
|
||||
|
||||
public ByteArrayImageSource(byte[] data) {
|
||||
this(data, 0, data.length);
|
||||
}
|
||||
|
||||
public ByteArrayImageSource(byte[] data, int offset, int length) {
|
||||
imagedata = data;
|
||||
imageoffset = offset;
|
||||
imagelength = length;
|
||||
}
|
||||
|
||||
final boolean checkSecurity(Object context, boolean quiet) {
|
||||
// No need to check security. Applets and downloaded code can
|
||||
// only make byte array image once they already have a handle
|
||||
// on the image data anyway...
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ImageDecoder getDecoder() {
|
||||
InputStream is =
|
||||
new BufferedInputStream(new ByteArrayInputStream(imagedata,
|
||||
imageoffset,
|
||||
imagelength));
|
||||
return getDecoder(is);
|
||||
}
|
||||
}
|
||||
834
jdkSrc/jdk8/sun/awt/image/ByteBandedRaster.java
Normal file
834
jdkSrc/jdk8/sun/awt/image/ByteBandedRaster.java
Normal file
@@ -0,0 +1,834 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.BandedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of multiple
|
||||
* 8-bit samples stored in possibly separate arrays for each band.
|
||||
* Operations on sets of pixels are performed on a given band in the
|
||||
* Raster before moving on to the next band. The arrays used for
|
||||
* storage may be distinct or shared between some or all of the bands.
|
||||
* Each band additionally has an offset that is added to determine the
|
||||
* DataBuffer location of each pixel.
|
||||
*
|
||||
* There is only one scanline stride for all bands. The pixel stride
|
||||
* is always equal to one. This type of raster can be used with a
|
||||
* ComponentColorModel. This class requires a BandedSampleModel.
|
||||
*
|
||||
*/
|
||||
public class ByteBandedRaster extends SunWritableRaster {
|
||||
|
||||
/** Data offsets for each band of image data. */
|
||||
int[] dataOffsets;
|
||||
|
||||
/** Scanline stride of the image data contained in this Raster. */
|
||||
int scanlineStride;
|
||||
|
||||
/** The image data array. */
|
||||
byte[][] data;
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
/**
|
||||
* Constructs a ByteBandedRaster with the given sampleModel. The
|
||||
* Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A dataBuffer large
|
||||
* enough to describe the Raster is automatically created. SampleModel
|
||||
* must be of type BandedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public ByteBandedRaster(SampleModel sampleModel,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ByteBanded Raster with the given sampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same size as the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferShort compatible with SampleModel.
|
||||
* SampleModel must be of type BandedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferShort that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public ByteBandedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel, dataBuffer,
|
||||
new Rectangle(origin.x , origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ByteBandedRaster with the given sampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferShort and
|
||||
* SampleModel must be of type BandedSampleModel.
|
||||
* When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coordinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferShort that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public ByteBandedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
ByteBandedRaster parent) {
|
||||
|
||||
super(sampleModel, dataBuffer, aRegion, origin, parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
|
||||
if (!(dataBuffer instanceof DataBufferByte)) {
|
||||
throw new RasterFormatException("ByteBandedRaster must have" +
|
||||
"byte DataBuffers");
|
||||
}
|
||||
DataBufferByte dbb = (DataBufferByte)dataBuffer;
|
||||
|
||||
if (sampleModel instanceof BandedSampleModel) {
|
||||
BandedSampleModel bsm = (BandedSampleModel)sampleModel;
|
||||
this.scanlineStride = bsm.getScanlineStride();
|
||||
int bankIndices[] = bsm.getBankIndices();
|
||||
int bandOffsets[] = bsm.getBandOffsets();
|
||||
int dOffsets[] = dbb.getOffsets();
|
||||
dataOffsets = new int[bankIndices.length];
|
||||
data = new byte[bankIndices.length][];
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
for (int i = 0; i < bankIndices.length; i++) {
|
||||
data[i] = stealData(dbb, bankIndices[i]);
|
||||
dataOffsets[i] = dOffsets[bankIndices[i]] +
|
||||
xOffset + yOffset*scanlineStride + bandOffsets[i];
|
||||
}
|
||||
} else {
|
||||
throw new RasterFormatException("ByteBandedRasters must have"+
|
||||
"BandedSampleModels");
|
||||
}
|
||||
verify();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data
|
||||
* offset is the index into the band's data array, of the first sample
|
||||
* of the band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[])dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data offset for the specified band. The data offset
|
||||
* is the index into the band's data array
|
||||
* in which the first sample of the first scanline is stored.
|
||||
* @param The band whose offset is returned.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements
|
||||
* between a given sample and the sample in the same column
|
||||
* of the next row in the same band.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pixel stride, which is always equal to one for
|
||||
* a Raster with a BandedSampleModel.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the entire data array.
|
||||
*/
|
||||
public byte[][] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the specific band data array.
|
||||
*/
|
||||
public byte[] getDataStorage(int band) {
|
||||
return data[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte outData[];
|
||||
if (obj == null) {
|
||||
outData = new byte[numDataElements];
|
||||
} else {
|
||||
outData = (byte[])obj;
|
||||
}
|
||||
int off = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int band = 0; band < numDataElements; band++) {
|
||||
outData[band] = data[band][dataOffsets[band] + off];
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified
|
||||
* rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* <pre>
|
||||
* byte[] bandData = (byte[])raster.getDataElement(x, y, w, h, null);
|
||||
* int numDataElements = raster.getNumDataElements();
|
||||
* byte[] pixel = new byte[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte outData[];
|
||||
if (obj == null) {
|
||||
outData = new byte[numDataElements*w*h];
|
||||
} else {
|
||||
outData = (byte[])obj;
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
byte[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
outData[off] = bank[xoff++];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte array of data elements from the specified rectangular
|
||||
* region for the specified band.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* byte[] bandData = raster.getByteData(x, y, w, h, null);
|
||||
* // To find the data element at location (x2, y2)
|
||||
* byte bandElement = bandData[((y2-y)*w + (x2-x))];
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param band The band to return.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public byte[] getByteData(int x, int y, int w, int h,
|
||||
int band, byte[] outData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new byte[scanlineStride*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[band];
|
||||
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(data[band], yoff, outData, 0, w*h);
|
||||
} else {
|
||||
int off = 0;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(data[band], yoff, outData, off, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* byte[] bandData = raster.getByteData(x, y, w, h, null);
|
||||
* int numDataElements = raster.getNumDataElements();
|
||||
* byte[] pixel = new byte[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new byte[numDataElements*scanlineStride*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
byte[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
// REMIND: Should keep track if dataoffsets are in a nice order
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
outData[off] = bank[xoff++];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the data elements for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte inData[] = (byte[])obj;
|
||||
int off = (y-minY)*scanlineStride + (x-minX);
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
data[i][dataOffsets[i] + off] = inData[i];
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Raster inRaster) {
|
||||
int dstOffX = inRaster.getMinX() + x;
|
||||
int dstOffY = inRaster.getMinY() + y;
|
||||
int width = inRaster.getWidth();
|
||||
int height = inRaster.getHeight();
|
||||
if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
|
||||
(dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
Object tdata = null;
|
||||
|
||||
// // REMIND: Do something faster!
|
||||
// if (inRaster instanceof ByteBandedRaster) {
|
||||
// }
|
||||
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
// Grab one scanline at a time
|
||||
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, tdata);
|
||||
setDataElements(dstX, dstY+startY, width, 1, tdata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte inData[] = (byte[])obj;
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
byte[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
bank[xoff++] = inData[off];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a byte array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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 band The band to set.
|
||||
* @param inData The data elements to be stored.
|
||||
*/
|
||||
public void putByteData(int x, int y, int w, int h,
|
||||
int band, byte[] inData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(inData, 0, data[band], yoff, w*h);
|
||||
} else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(inData, off, data[band], yoff, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a byte array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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 The data elements to be stored.
|
||||
*/
|
||||
public void putByteData(int x, int y, int w, int h, byte[] inData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
byte[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
bank[xoff++] = inData[off];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Writable subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* DataBuffers as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width of the subraster.
|
||||
* @param height Height of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.width + this.minX)) {
|
||||
throw new RasterFormatException("(x + width) is outside raster") ;
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.height + this.minY)) {
|
||||
throw new RasterFormatException("(y + height) is outside raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new ByteBandedRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0,y0,width,height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* DataBuffers as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
return createWritableChild(x, y, width, height, x0, y0, bandList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w,h);
|
||||
|
||||
return new ByteBandedRaster(sm, new Point(0,0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the Raster is a subRaster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
* Verifies whether the data buffer has enough data for the raster,
|
||||
* taking into account offsets, after ensuring all offsets are >=0.
|
||||
* @throws RasterFormatException if a problem is detected.
|
||||
*/
|
||||
private void verify() {
|
||||
|
||||
/* Need to re-verify the dimensions since a sample model may be
|
||||
* specified to the constructor
|
||||
*/
|
||||
if (width <= 0 || height <= 0 ||
|
||||
height > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
|
||||
if ((long)minX - sampleModelTranslateX < 0 ||
|
||||
(long)minY - sampleModelTranslateY < 0) {
|
||||
|
||||
throw new RasterFormatException("Incorrect origin/translate: (" +
|
||||
minX + ", " + minY + ") / (" +
|
||||
sampleModelTranslateX + ", " + sampleModelTranslateY + ")");
|
||||
}
|
||||
|
||||
|
||||
if (height > 1 || minY - sampleModelTranslateY > 0) {
|
||||
// buffer should contain at least one scanline
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
if (scanlineStride > data[i].length) {
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure data for Raster is in a legal range
|
||||
for (int i=0; i < dataOffsets.length; i++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band "+i+
|
||||
"("+dataOffsets[i]+
|
||||
") must be >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
|
||||
if ((width - 1) > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
int lastPixelOffset = lastScanOffset + (width-1);
|
||||
|
||||
int maxIndex = 0;
|
||||
int index;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
index = lastPixelOffset + dataOffsets[i];
|
||||
if (index > maxIndex) {
|
||||
maxIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.length == 1) {
|
||||
if (data[0].length <= maxIndex*numDataElements) {
|
||||
throw new RasterFormatException("Data array too small "+
|
||||
"(it is "+data[0].length+
|
||||
" and should be > "+
|
||||
(maxIndex*numDataElements)+
|
||||
" )");
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
if (data[i].length <= maxIndex) {
|
||||
throw new RasterFormatException("Data array too small "+
|
||||
"(it is "+data[i].length+
|
||||
" and should be > "+
|
||||
maxIndex+" )");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ByteBandedRaster: width = "+width+" height = "
|
||||
+ height
|
||||
+" #bands "+numDataElements
|
||||
+" minX = "+minX+" minY = "+minY);
|
||||
}
|
||||
|
||||
}
|
||||
983
jdkSrc/jdk8/sun/awt/image/ByteComponentRaster.java
Normal file
983
jdkSrc/jdk8/sun/awt/image/ByteComponentRaster.java
Normal file
@@ -0,0 +1,983 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of one or more 8-bit
|
||||
* data elements stored in close proximity to each other in a single byte
|
||||
* array.
|
||||
* The bit precision per data element is that
|
||||
* of the data type (that is, the bit precision for this Raster is 8).
|
||||
* There is only one pixel stride and one scanline stride for all
|
||||
* bands. This type of Raster can be used with a
|
||||
* ComponentColorModel if there are multiple bands, or an
|
||||
* IndexColorModel if there is only one band.
|
||||
* <p>
|
||||
* For example, 3-3-2 RGB image data can be represented by a
|
||||
* ByteComponentRaster using a SinglePixelPackedSampleModel and
|
||||
* a ComponentColorModel.
|
||||
*
|
||||
*/
|
||||
public class ByteComponentRaster extends SunWritableRaster {
|
||||
|
||||
/** private band offset for use by native code */
|
||||
protected int bandOffset;
|
||||
|
||||
/** Data offsets for each band of image data. */
|
||||
protected int[] dataOffsets;
|
||||
|
||||
/** Scanline stride of the image data contained in this Raster. */
|
||||
protected int scanlineStride;
|
||||
|
||||
/** Pixel stride of the image data contained in this Raster. */
|
||||
protected int pixelStride;
|
||||
|
||||
/** The image data array. */
|
||||
protected byte[] data;
|
||||
|
||||
int type;
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
static private native void initIDs();
|
||||
static {
|
||||
/* ensure that the necessary native libraries are loaded */
|
||||
NativeLibLoader.loadLibraries();
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ByteComponentRaster with the given SampleModel.
|
||||
* The Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A DataBuffer large enough to describe the
|
||||
* Raster is automatically created. SampleModel must be of type
|
||||
* SinglePixelPackedSampleModel or ComponentSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specified the origin.
|
||||
*/
|
||||
public ByteComponentRaster(SampleModel sampleModel, Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ByteComponentRaster with the given SampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same size as the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferByte compatible with SampleModel.
|
||||
* SampleModel must be of type SinglePixelPackedSampleModel
|
||||
* or ComponentSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferShort that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public ByteComponentRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
dataBuffer,
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ByteComponentRaster with the given SampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferByte and
|
||||
* SampleModel must be of type SinglePixelPackedSampleModel
|
||||
* or ComponentSampleModel.
|
||||
* When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coordinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferShort that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public ByteComponentRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
ByteComponentRaster parent) {
|
||||
super(sampleModel, dataBuffer, aRegion, origin, parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
|
||||
if (!(dataBuffer instanceof DataBufferByte)) {
|
||||
throw new RasterFormatException("ByteComponentRasters must have " +
|
||||
"byte DataBuffers");
|
||||
}
|
||||
|
||||
DataBufferByte dbb = (DataBufferByte)dataBuffer;
|
||||
this.data = stealData(dbb, 0);
|
||||
if (dbb.getNumBanks() != 1) {
|
||||
throw new
|
||||
RasterFormatException("DataBuffer for ByteComponentRasters"+
|
||||
" must only have 1 bank.");
|
||||
}
|
||||
int dbOffset = dbb.getOffset();
|
||||
|
||||
if (sampleModel instanceof ComponentSampleModel) {
|
||||
ComponentSampleModel ism = (ComponentSampleModel)sampleModel;
|
||||
this.type = IntegerComponentRaster.TYPE_BYTE_SAMPLES;
|
||||
this.scanlineStride = ism.getScanlineStride();
|
||||
this.pixelStride = ism.getPixelStride();
|
||||
this.dataOffsets = ism.getBandOffsets();
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
for (int i = 0; i < getNumDataElements(); i++) {
|
||||
dataOffsets[i] += dbOffset +
|
||||
xOffset*pixelStride+yOffset*scanlineStride;
|
||||
}
|
||||
} else if (sampleModel instanceof SinglePixelPackedSampleModel) {
|
||||
SinglePixelPackedSampleModel sppsm =
|
||||
(SinglePixelPackedSampleModel)sampleModel;
|
||||
this.type = IntegerComponentRaster.TYPE_BYTE_PACKED_SAMPLES;
|
||||
this.scanlineStride = sppsm.getScanlineStride();
|
||||
this.pixelStride = 1;
|
||||
this.dataOffsets = new int[1];
|
||||
this.dataOffsets[0] = dbOffset;
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride;
|
||||
} else {
|
||||
throw new RasterFormatException("IntegerComponentRasters must " +
|
||||
"have ComponentSampleModel or SinglePixelPackedSampleModel");
|
||||
}
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data offset
|
||||
* is the index into the band's data array, of the first sample of the
|
||||
* band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[]) dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data offset for the specified band. The data offset
|
||||
* is the index into the data array
|
||||
* in which the first sample of the first scanline is stored.
|
||||
* @param band The band whose offset is returned.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements between
|
||||
* a given sample and the sample in the same column of the next row in the
|
||||
* same band.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel stride -- the number of data array elements between two
|
||||
* samples for the same band on the same scanline.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return pixelStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the data array.
|
||||
*/
|
||||
public byte[] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte outData[];
|
||||
if (obj == null) {
|
||||
outData = new byte[numDataElements];
|
||||
} else {
|
||||
outData = (byte[])obj;
|
||||
}
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
for (int band = 0; band < numDataElements; band++) {
|
||||
outData[band] = data[dataOffsets[band] + off];
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* <pre>
|
||||
* byte[] bandData = (byte[])raster.getDataElements(x, y, w, h, null);
|
||||
* int numDataElements = raster.getNumDataElements();
|
||||
* byte[] pixel = new byte[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte outData[];
|
||||
if (obj == null) {
|
||||
outData = new byte[w*h*numDataElements];
|
||||
} else {
|
||||
outData = (byte[])obj;
|
||||
}
|
||||
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte array of data elements from the specified rectangular
|
||||
* region for the specified band.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* byte[] bandData = raster.getByteData(x, y, w, h, null);
|
||||
* // To find the data element at location (x2, y2)
|
||||
* byte bandElement = bandData[((y2-y)*w + (x2-x))];
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param band The band to return.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public byte[] getByteData(int x, int y, int w, int h,
|
||||
int band, byte[] outData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new byte[scanlineStride*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride + dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(data, yoff, outData, 0, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(data, yoff, outData, off, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
outData[off++] = data[xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* byte[] bandData = raster.getByteData(x, y, w, h, null);
|
||||
* int numDataElements = raster.getnumDataElements();
|
||||
* byte[] pixel = new byte[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new byte[numDataElements*scanlineStride*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
// REMIND: Should keep track if dataOffsets are in a nice order
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the data elements for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte inData[] = (byte[])obj;
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
data[dataOffsets[i] + off] = inData[i];
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Raster inRaster) {
|
||||
int dstOffX = inRaster.getMinX() + x;
|
||||
int dstOffY = inRaster.getMinY() + y;
|
||||
int width = inRaster.getWidth();
|
||||
int height = inRaster.getHeight();
|
||||
if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
|
||||
(dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
Object tdata = null;
|
||||
|
||||
if (inRaster instanceof ByteComponentRaster) {
|
||||
ByteComponentRaster bct = (ByteComponentRaster) inRaster;
|
||||
byte[] bdata = bct.getDataStorage();
|
||||
// REMIND: Do something faster!
|
||||
if (numDataElements == 1) {
|
||||
int toff = bct.getDataOffset(0);
|
||||
int tss = bct.getScanlineStride();
|
||||
|
||||
int srcOffset = toff;
|
||||
int dstOffset = dataOffsets[0]+(dstY-minY)*scanlineStride+
|
||||
(dstX-minX);
|
||||
|
||||
|
||||
if (pixelStride == bct.getPixelStride()) {
|
||||
width *= pixelStride;
|
||||
for (int tmpY=0; tmpY < height; tmpY++) {
|
||||
System.arraycopy(bdata, srcOffset,
|
||||
data, dstOffset, width);
|
||||
srcOffset += tss;
|
||||
dstOffset += scanlineStride;
|
||||
}
|
||||
markDirty();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
// Grab one scanline at a time
|
||||
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, tdata);
|
||||
setDataElements(dstX, dstY+startY, width, 1, tdata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
byte inData[] = (byte[])obj;
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (numDataElements == 1) {
|
||||
int srcOffset = 0;
|
||||
int dstOffset = yoff + dataOffsets[0];
|
||||
for (ystart=0; ystart < h; ystart++) {
|
||||
xoff = yoff;
|
||||
System.arraycopy(inData, srcOffset,
|
||||
data, dstOffset, w);
|
||||
|
||||
srcOffset += w;
|
||||
dstOffset += scanlineStride;
|
||||
}
|
||||
markDirty();
|
||||
return;
|
||||
}
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a byte array of data elements into the specified rectangular
|
||||
* region for the specified band.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x)) + n]
|
||||
* </pre>
|
||||
* @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 band The band to set.
|
||||
* @param inData The data elements to be stored.
|
||||
*/
|
||||
public void putByteData(int x, int y, int w, int h,
|
||||
int band, byte[] inData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride + dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(inData, 0, data, yoff, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(inData, off, data, yoff, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
data[xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a byte array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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 The data elements to be stored.
|
||||
*/
|
||||
public void putByteData(int x, int y, int w, int h, byte[] inData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (numDataElements == 1) {
|
||||
yoff += dataOffsets[0];
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(inData, 0, data, yoff, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++) {
|
||||
System.arraycopy(inData, off, data, yoff, w);
|
||||
off += w;
|
||||
yoff += scanlineStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
data[xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* DataBuffer as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild(int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0, int[] bandList) {
|
||||
WritableRaster newRaster = createWritableChild(x, y,
|
||||
width, height,
|
||||
x0, y0,
|
||||
bandList);
|
||||
return (Raster) newRaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Writable subRaster given a region of the Raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this Raster to the upper-left corner
|
||||
* of the subRaster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subRaster will reference the same
|
||||
* DataBuffer as the parent Raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent Raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild(int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int[] bandList) {
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside the raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside the raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.minX + this.width)) {
|
||||
throw new RasterFormatException("(x + width) is outside of Raster");
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.minY + this.height)) {
|
||||
throw new RasterFormatException("(y + height) is outside of Raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new ByteComponentRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0, y0, width, height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
|
||||
|
||||
return new ByteComponentRaster(sm , new Point(0,0));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the Raster is a subRaster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
*
|
||||
* The method verifies whether scanline stride and pixel stride do not
|
||||
* cause an integer overflow during calculation of a position of the pixel
|
||||
* in data buffer. It also verifies whether the data buffer has enough data
|
||||
* to correspond the raster layout attributes.
|
||||
*
|
||||
* @throws RasterFormatException if an integer overflow is detected,
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
protected final void verify() {
|
||||
/* Need to re-verify the dimensions since a sample model may be
|
||||
* specified to the constructor
|
||||
*/
|
||||
if (width <= 0 || height <= 0 ||
|
||||
height > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
|
||||
for (int i = 0; i < dataOffsets.length; i++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band " + i
|
||||
+ "(" + dataOffsets[i]
|
||||
+ ") must be >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
if ((long)minX - sampleModelTranslateX < 0 ||
|
||||
(long)minY - sampleModelTranslateY < 0) {
|
||||
|
||||
throw new RasterFormatException("Incorrect origin/translate: (" +
|
||||
minX + ", " + minY + ") / (" +
|
||||
sampleModelTranslateX + ", " + sampleModelTranslateY + ")");
|
||||
}
|
||||
|
||||
// we can be sure that width and height are greater than 0
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
|
||||
if (height > 1 || minY - sampleModelTranslateY > 0) {
|
||||
// buffer should contain at least one scanline
|
||||
if (scanlineStride > data.length) {
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
}
|
||||
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
|
||||
if (pixelStride < 0 ||
|
||||
pixelStride > (Integer.MAX_VALUE / width) ||
|
||||
pixelStride > data.length)
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect pixel stride: "
|
||||
+ pixelStride);
|
||||
}
|
||||
int lastPixelOffset = (width - 1) * pixelStride;
|
||||
|
||||
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect raster attributes");
|
||||
}
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
int index;
|
||||
int maxIndex = 0;
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
|
||||
}
|
||||
|
||||
index = lastPixelOffset + dataOffsets[i];
|
||||
|
||||
if (index > maxIndex) {
|
||||
maxIndex = index;
|
||||
}
|
||||
}
|
||||
if (data.length <= maxIndex) {
|
||||
throw new RasterFormatException("Data array too small (should be > "
|
||||
+ maxIndex + " )");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ByteComponentRaster: width = "+width+" height = "
|
||||
+ height
|
||||
+" #numDataElements "+numDataElements
|
||||
// +" xOff = "+xOffset+" yOff = "+yOffset
|
||||
+" dataOff[0] = "+dataOffsets[0]);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * For debugging... prints a region of a one-band ByteComponentRaster
|
||||
// */
|
||||
// public void print(int x, int y, int w, int h) {
|
||||
// // REMIND: Only works for 1 band!
|
||||
// System.out.println(this);
|
||||
// int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride;
|
||||
// int off;
|
||||
// for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) {
|
||||
// off = offset;
|
||||
// System.out.print("Line "+(y+yoff)+": ");
|
||||
// for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) {
|
||||
// String s = Integer.toHexString(data[off]);
|
||||
// if (s.length() == 8) {
|
||||
// s = s.substring(6,8);
|
||||
// }
|
||||
// System.out.print(s+" ");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
1324
jdkSrc/jdk8/sun/awt/image/ByteInterleavedRaster.java
Normal file
1324
jdkSrc/jdk8/sun/awt/image/ByteInterleavedRaster.java
Normal file
File diff suppressed because it is too large
Load Diff
1436
jdkSrc/jdk8/sun/awt/image/BytePackedRaster.java
Normal file
1436
jdkSrc/jdk8/sun/awt/image/BytePackedRaster.java
Normal file
File diff suppressed because it is too large
Load Diff
92
jdkSrc/jdk8/sun/awt/image/DataBufferNative.java
Normal file
92
jdkSrc/jdk8/sun/awt/image/DataBufferNative.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 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 sun.awt.image;
|
||||
|
||||
import java.awt.image.DataBuffer;
|
||||
import sun.java2d.SurfaceData;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
/**
|
||||
* This class extends <CODE>DataBuffer</CODE> and allows access to
|
||||
* native data via the DataBuffer methods. Note that, unlike other
|
||||
* DataBuffer classes, the data is not stored in this class but
|
||||
* has been created and stored elsewhere and this class is used
|
||||
* merely to access that data. Note also that this class subclasses
|
||||
* from DataBuffer and not from any of the standard subclasses
|
||||
* (e.g., DataBufferInt); those subclasses allow the user to
|
||||
* get a pointer to the data and manipulate it directly. That
|
||||
* operation may not be possible or wise with native data.
|
||||
* One important use of this DataBuffer class is in accessing the
|
||||
* data stored in an offscreen vram surface, such as that created
|
||||
* by the createVolatileImage() method.
|
||||
*/
|
||||
|
||||
public class DataBufferNative extends DataBuffer
|
||||
{
|
||||
protected SurfaceData surfaceData;
|
||||
protected int width;
|
||||
|
||||
/**
|
||||
* Constructor. The constructor of this object requires a
|
||||
* SurfaceData object; that surfaceData object will be used
|
||||
* to access the actual pixel data in native code.
|
||||
*/
|
||||
public DataBufferNative(SurfaceData sData, int type, int width, int height) {
|
||||
super(type, width*height);
|
||||
this.width = width;
|
||||
this.surfaceData = sData;
|
||||
}
|
||||
|
||||
protected native int getElem(int x, int y, SurfaceData sData);
|
||||
|
||||
/**
|
||||
* getElem returns the pixel value for a given index into the
|
||||
* dataBuffer array. The bank value is currently ignored (the
|
||||
* type of data accessed through this class is not stored in
|
||||
* separate banks). The x and y coordinates of a pixel are calculated
|
||||
* from the index value and the native getElem() method is
|
||||
* called with the internal surfaceData object.
|
||||
*/
|
||||
public int getElem(int bank, int i) {
|
||||
return getElem(i % width, i / width, surfaceData);
|
||||
}
|
||||
|
||||
protected native void setElem(int x, int y, int val, SurfaceData sData);
|
||||
|
||||
/**
|
||||
* setElem sets the pixel value of a given index into the
|
||||
* dataBuffer array. The bank value is currently ignored (the
|
||||
* type of data accessed through this class is not stored in
|
||||
* separate banks). The x and y coordinates of a pixel are calculated
|
||||
* from the index value and the native setElem() method is
|
||||
* called with the internal surfaceData object.
|
||||
*/
|
||||
public void setElem(int bank, int i, int val) {
|
||||
setElem(i % width, i / width, val, surfaceData);
|
||||
}
|
||||
|
||||
}
|
||||
79
jdkSrc/jdk8/sun/awt/image/FileImageSource.java
Normal file
79
jdkSrc/jdk8/sun/awt/image/FileImageSource.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1996, 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 sun.awt.image;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
public class FileImageSource extends InputStreamImageSource {
|
||||
String imagefile;
|
||||
|
||||
public FileImageSource(String filename) {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkRead(filename);
|
||||
}
|
||||
imagefile = filename;
|
||||
}
|
||||
|
||||
final boolean checkSecurity(Object context, boolean quiet) {
|
||||
// File based images only ever need to be checked statically
|
||||
// when the image is retrieved from the cache.
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ImageDecoder getDecoder() {
|
||||
if (imagefile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
InputStream is;
|
||||
try {
|
||||
is = new BufferedInputStream(new FileInputStream(imagefile));
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
// Don't believe the file suffix - many users don't know what
|
||||
// kind of image they have and guess wrong...
|
||||
/*
|
||||
int suffixpos = imagefile.lastIndexOf('.');
|
||||
if (suffixpos >= 0) {
|
||||
String suffix = imagefile.substring(suffixpos+1).toLowerCase();
|
||||
if (suffix.equals("gif")) {
|
||||
return new GifImageDecoder(this, is);
|
||||
} else if (suffix.equals("jpeg") || suffix.equals("jpg") ||
|
||||
suffix.equals("jpe") || suffix.equals("jfif")) {
|
||||
return new JPEGImageDecoder(this, is);
|
||||
} else if (suffix.equals("xbm")) {
|
||||
return new XbmImageDecoder(this, is);
|
||||
}
|
||||
}
|
||||
*/
|
||||
return getDecoder(is);
|
||||
}
|
||||
}
|
||||
753
jdkSrc/jdk8/sun/awt/image/GifImageDecoder.java
Normal file
753
jdkSrc/jdk8/sun/awt/image/GifImageDecoder.java
Normal file
@@ -0,0 +1,753 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Reads GIF images from an InputStream and reports the
|
||||
* image data to an InputStreamImageSource object.
|
||||
*
|
||||
* The algorithm is copyright of CompuServe.
|
||||
*/
|
||||
package sun.awt.image;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Hashtable;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* Gif Image converter
|
||||
*
|
||||
* @author Arthur van Hoff
|
||||
* @author Jim Graham
|
||||
*/
|
||||
public class GifImageDecoder extends ImageDecoder {
|
||||
private static final boolean verbose = false;
|
||||
|
||||
private static final int IMAGESEP = 0x2c;
|
||||
private static final int EXBLOCK = 0x21;
|
||||
private static final int EX_GRAPHICS_CONTROL= 0xf9;
|
||||
private static final int EX_COMMENT = 0xfe;
|
||||
private static final int EX_APPLICATION = 0xff;
|
||||
private static final int TERMINATOR = 0x3b;
|
||||
private static final int TRANSPARENCYMASK = 0x01;
|
||||
private static final int INTERLACEMASK = 0x40;
|
||||
private static final int COLORMAPMASK = 0x80;
|
||||
|
||||
int num_global_colors;
|
||||
byte[] global_colormap;
|
||||
int trans_pixel = -1;
|
||||
IndexColorModel global_model;
|
||||
|
||||
Hashtable props = new Hashtable();
|
||||
|
||||
byte[] saved_image;
|
||||
IndexColorModel saved_model;
|
||||
|
||||
int global_width;
|
||||
int global_height;
|
||||
int global_bgpixel;
|
||||
|
||||
GifFrame curframe;
|
||||
|
||||
public GifImageDecoder(InputStreamImageSource src, InputStream is) {
|
||||
super(src, is);
|
||||
}
|
||||
|
||||
/**
|
||||
* An error has occurred. Throw an exception.
|
||||
*/
|
||||
private static void error(String s1) throws ImageFormatException {
|
||||
throw new ImageFormatException(s1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a number of bytes into a buffer.
|
||||
* @return number of bytes that were not read due to EOF or error
|
||||
*/
|
||||
private int readBytes(byte buf[], int off, int len) {
|
||||
while (len > 0) {
|
||||
try {
|
||||
int n = input.read(buf, off, len);
|
||||
if (n < 0) {
|
||||
break;
|
||||
}
|
||||
off += n;
|
||||
len -= n;
|
||||
} catch (IOException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
private static final int ExtractByte(byte buf[], int off) {
|
||||
return (buf[off] & 0xFF);
|
||||
}
|
||||
|
||||
private static final int ExtractWord(byte buf[], int off) {
|
||||
return (buf[off] & 0xFF) | ((buf[off + 1] & 0xFF) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* produce an image from the stream.
|
||||
*/
|
||||
public void produceImage() throws IOException, ImageFormatException {
|
||||
try {
|
||||
readHeader();
|
||||
|
||||
int totalframes = 0;
|
||||
int frameno = 0;
|
||||
int nloops = -1;
|
||||
int disposal_method = 0;
|
||||
int delay = -1;
|
||||
boolean loopsRead = false;
|
||||
boolean isAnimation = false;
|
||||
|
||||
while (!aborted) {
|
||||
int code;
|
||||
|
||||
switch (code = input.read()) {
|
||||
case EXBLOCK:
|
||||
switch (code = input.read()) {
|
||||
case EX_GRAPHICS_CONTROL: {
|
||||
byte buf[] = new byte[6];
|
||||
if (readBytes(buf, 0, 6) != 0) {
|
||||
return;//error("corrupt GIF file");
|
||||
}
|
||||
if ((buf[0] != 4) || (buf[5] != 0)) {
|
||||
return;//error("corrupt GIF file (GCE size)");
|
||||
}
|
||||
// Get the index of the transparent color
|
||||
delay = ExtractWord(buf, 2) * 10;
|
||||
if (delay > 0 && !isAnimation) {
|
||||
isAnimation = true;
|
||||
ImageFetcher.startingAnimation();
|
||||
}
|
||||
disposal_method = (buf[1] >> 2) & 7;
|
||||
if ((buf[1] & TRANSPARENCYMASK) != 0) {
|
||||
trans_pixel = ExtractByte(buf, 4);
|
||||
} else {
|
||||
trans_pixel = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EX_COMMENT:
|
||||
case EX_APPLICATION:
|
||||
default:
|
||||
boolean loop_tag = false;
|
||||
String comment = "";
|
||||
while (true) {
|
||||
int n = input.read();
|
||||
if (n <= 0) {
|
||||
break;
|
||||
}
|
||||
byte buf[] = new byte[n];
|
||||
if (readBytes(buf, 0, n) != 0) {
|
||||
return;//error("corrupt GIF file");
|
||||
}
|
||||
if (code == EX_COMMENT) {
|
||||
comment += new String(buf, 0);
|
||||
} else if (code == EX_APPLICATION) {
|
||||
if (loop_tag) {
|
||||
if (n == 3 && buf[0] == 1) {
|
||||
if (loopsRead) {
|
||||
ExtractWord(buf, 1);
|
||||
}
|
||||
else {
|
||||
nloops = ExtractWord(buf, 1);
|
||||
loopsRead = true;
|
||||
}
|
||||
} else {
|
||||
loop_tag = false;
|
||||
}
|
||||
}
|
||||
if ("NETSCAPE2.0".equals(new String(buf, 0))) {
|
||||
loop_tag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (code == EX_COMMENT) {
|
||||
props.put("comment", comment);
|
||||
}
|
||||
if (loop_tag && !isAnimation) {
|
||||
isAnimation = true;
|
||||
ImageFetcher.startingAnimation();
|
||||
}
|
||||
break;
|
||||
|
||||
case -1:
|
||||
return; //error("corrupt GIF file");
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGESEP:
|
||||
if (!isAnimation) {
|
||||
input.mark(0); // we don't need the mark buffer
|
||||
}
|
||||
try {
|
||||
if (!readImage(totalframes == 0,
|
||||
disposal_method,
|
||||
delay)) {
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (verbose) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
frameno++;
|
||||
totalframes++;
|
||||
break;
|
||||
|
||||
default:
|
||||
case -1:
|
||||
if (verbose) {
|
||||
if (code == -1) {
|
||||
System.err.println("Premature EOF in GIF file," +
|
||||
" frame " + frameno);
|
||||
} else {
|
||||
System.err.println("corrupt GIF file (parse) ["
|
||||
+ code + "].");
|
||||
}
|
||||
}
|
||||
if (frameno == 0) {
|
||||
return;
|
||||
}
|
||||
// NOBREAK
|
||||
|
||||
case TERMINATOR:
|
||||
if (nloops == 0 || nloops-- >= 0) {
|
||||
try {
|
||||
if (curframe != null) {
|
||||
curframe.dispose();
|
||||
curframe = null;
|
||||
}
|
||||
input.reset();
|
||||
saved_image = null;
|
||||
saved_model = null;
|
||||
frameno = 0;
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
return; // Unable to reset input buffer
|
||||
}
|
||||
}
|
||||
if (verbose && frameno != 1) {
|
||||
System.out.println("processing GIF terminator,"
|
||||
+ " frames: " + frameno
|
||||
+ " total: " + totalframes);
|
||||
}
|
||||
imageComplete(ImageConsumer.STATICIMAGEDONE, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read Image header
|
||||
*/
|
||||
private void readHeader() throws IOException, ImageFormatException {
|
||||
// Create a buffer
|
||||
byte buf[] = new byte[13];
|
||||
|
||||
// Read the header
|
||||
if (readBytes(buf, 0, 13) != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
// Check header
|
||||
if ((buf[0] != 'G') || (buf[1] != 'I') || (buf[2] != 'F')) {
|
||||
error("not a GIF file.");
|
||||
}
|
||||
|
||||
// Global width&height
|
||||
global_width = ExtractWord(buf, 6);
|
||||
global_height = ExtractWord(buf, 8);
|
||||
|
||||
// colormap info
|
||||
int ch = ExtractByte(buf, 10);
|
||||
if ((ch & COLORMAPMASK) == 0) {
|
||||
// no global colormap so make up our own
|
||||
// If there is a local colormap, it will override what we
|
||||
// have here. If there is not a local colormap, the rules
|
||||
// for GIF89 say that we can use whatever colormap we want.
|
||||
// This means that we should probably put in a full 256 colormap
|
||||
// at some point. REMIND!
|
||||
num_global_colors = 2;
|
||||
global_bgpixel = 0;
|
||||
global_colormap = new byte[2*3];
|
||||
global_colormap[0] = global_colormap[1] = global_colormap[2] = (byte)0;
|
||||
global_colormap[3] = global_colormap[4] = global_colormap[5] = (byte)255;
|
||||
|
||||
}
|
||||
else {
|
||||
num_global_colors = 1 << ((ch & 0x7) + 1);
|
||||
|
||||
global_bgpixel = ExtractByte(buf, 11);
|
||||
|
||||
if (buf[12] != 0) {
|
||||
props.put("aspectratio", ""+((ExtractByte(buf, 12) + 15) / 64.0));
|
||||
}
|
||||
|
||||
// Read colors
|
||||
global_colormap = new byte[num_global_colors * 3];
|
||||
if (readBytes(global_colormap, 0, num_global_colors * 3) != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
input.mark(Integer.MAX_VALUE); // set this mark in case this is an animated GIF
|
||||
}
|
||||
|
||||
/**
|
||||
* The ImageConsumer hints flag for a non-interlaced GIF image.
|
||||
*/
|
||||
private static final int normalflags =
|
||||
ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME;
|
||||
|
||||
/**
|
||||
* The ImageConsumer hints flag for an interlaced GIF image.
|
||||
*/
|
||||
private static final int interlaceflags =
|
||||
ImageConsumer.RANDOMPIXELORDER | ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME;
|
||||
|
||||
private short prefix[] = new short[4096];
|
||||
private byte suffix[] = new byte[4096];
|
||||
private byte outCode[] = new byte[4097];
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
static {
|
||||
/* ensure that the necessary native libraries are loaded */
|
||||
NativeLibLoader.loadLibraries();
|
||||
initIDs();
|
||||
}
|
||||
|
||||
private native boolean parseImage(int x, int y, int width, int height,
|
||||
boolean interlace, int initCodeSize,
|
||||
byte block[], byte rasline[],
|
||||
IndexColorModel model);
|
||||
|
||||
private int sendPixels(int x, int y, int width, int height,
|
||||
byte rasline[], ColorModel model) {
|
||||
int rasbeg, rasend, x2;
|
||||
if (y < 0) {
|
||||
height += y;
|
||||
y = 0;
|
||||
}
|
||||
if (y + height > global_height) {
|
||||
height = global_height - y;
|
||||
}
|
||||
if (height <= 0) {
|
||||
return 1;
|
||||
}
|
||||
// rasline[0] == pixel at coordinate (x,y)
|
||||
// rasline[width] == pixel at coordinate (x+width, y)
|
||||
if (x < 0) {
|
||||
rasbeg = -x;
|
||||
width += x; // same as (width -= rasbeg)
|
||||
x2 = 0; // same as (x2 = x + rasbeg)
|
||||
} else {
|
||||
rasbeg = 0;
|
||||
// width -= 0; // same as (width -= rasbeg)
|
||||
x2 = x; // same as (x2 = x + rasbeg)
|
||||
}
|
||||
// rasline[rasbeg] == pixel at coordinate (x2,y)
|
||||
// rasline[width] == pixel at coordinate (x+width, y)
|
||||
// rasline[rasbeg + width] == pixel at coordinate (x2+width, y)
|
||||
if (x2 + width > global_width) {
|
||||
width = global_width - x2;
|
||||
}
|
||||
if (width <= 0) {
|
||||
return 1;
|
||||
}
|
||||
rasend = rasbeg + width;
|
||||
// rasline[rasbeg] == pixel at coordinate (x2,y)
|
||||
// rasline[rasend] == pixel at coordinate (x2+width, y)
|
||||
int off = y * global_width + x2;
|
||||
boolean save = (curframe.disposal_method == GifFrame.DISPOSAL_SAVE);
|
||||
if (trans_pixel >= 0 && !curframe.initialframe) {
|
||||
if (saved_image != null && model.equals(saved_model)) {
|
||||
for (int i = rasbeg; i < rasend; i++, off++) {
|
||||
byte pixel = rasline[i];
|
||||
if ((pixel & 0xff) == trans_pixel) {
|
||||
rasline[i] = saved_image[off];
|
||||
} else if (save) {
|
||||
saved_image[off] = pixel;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We have to do this the hard way - only transmit
|
||||
// the non-transparent sections of the line...
|
||||
// Fix for 6301050: the interlacing is ignored in this case
|
||||
// in order to avoid artefacts in case of animated images.
|
||||
int runstart = -1;
|
||||
int count = 1;
|
||||
for (int i = rasbeg; i < rasend; i++, off++) {
|
||||
byte pixel = rasline[i];
|
||||
if ((pixel & 0xff) == trans_pixel) {
|
||||
if (runstart >= 0) {
|
||||
count = setPixels(x + runstart, y,
|
||||
i - runstart, 1,
|
||||
model, rasline,
|
||||
runstart, 0);
|
||||
if (count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
runstart = -1;
|
||||
} else {
|
||||
if (runstart < 0) {
|
||||
runstart = i;
|
||||
}
|
||||
if (save) {
|
||||
saved_image[off] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (runstart >= 0) {
|
||||
count = setPixels(x + runstart, y,
|
||||
rasend - runstart, 1,
|
||||
model, rasline,
|
||||
runstart, 0);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
} else if (save) {
|
||||
System.arraycopy(rasline, rasbeg, saved_image, off, width);
|
||||
}
|
||||
int count = setPixels(x2, y, width, height, model,
|
||||
rasline, rasbeg, 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read Image data
|
||||
*/
|
||||
private boolean readImage(boolean first, int disposal_method, int delay)
|
||||
throws IOException
|
||||
{
|
||||
if (curframe != null && !curframe.dispose()) {
|
||||
abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
long tm = 0;
|
||||
|
||||
if (verbose) {
|
||||
tm = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Allocate the buffer
|
||||
byte block[] = new byte[256 + 3];
|
||||
|
||||
// Read the image descriptor
|
||||
if (readBytes(block, 0, 10) != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
int x = ExtractWord(block, 0);
|
||||
int y = ExtractWord(block, 2);
|
||||
int width = ExtractWord(block, 4);
|
||||
int height = ExtractWord(block, 6);
|
||||
|
||||
/*
|
||||
* Majority of gif images have
|
||||
* same logical screen and frame dimensions.
|
||||
* Also, Photoshop and Mozilla seem to use the logical
|
||||
* screen dimension (from the global stream header)
|
||||
* if frame dimension is invalid.
|
||||
*
|
||||
* We use similar heuristic and trying to recover
|
||||
* frame width from logical screen dimension and
|
||||
* frame offset.
|
||||
*/
|
||||
if (width == 0 && global_width != 0) {
|
||||
width = global_width - x;
|
||||
}
|
||||
if (height == 0 && global_height != 0) {
|
||||
height = global_height - y;
|
||||
}
|
||||
|
||||
boolean interlace = (block[8] & INTERLACEMASK) != 0;
|
||||
|
||||
IndexColorModel model = global_model;
|
||||
|
||||
if ((block[8] & COLORMAPMASK) != 0) {
|
||||
// We read one extra byte above so now when we must
|
||||
// transfer that byte as the first colormap byte
|
||||
// and manually read the code size when we are done
|
||||
int num_local_colors = 1 << ((block[8] & 0x7) + 1);
|
||||
|
||||
// Read local colors
|
||||
byte[] local_colormap = new byte[num_local_colors * 3];
|
||||
local_colormap[0] = block[9];
|
||||
if (readBytes(local_colormap, 1, num_local_colors * 3 - 1) != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
// Now read the "real" code size byte which follows
|
||||
// the local color table
|
||||
if (readBytes(block, 9, 1) != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
if (trans_pixel >= num_local_colors) {
|
||||
// Fix for 4233748: extend colormap to contain transparent pixel
|
||||
num_local_colors = trans_pixel + 1;
|
||||
local_colormap = grow_colormap(local_colormap, num_local_colors);
|
||||
}
|
||||
model = new IndexColorModel(8, num_local_colors, local_colormap,
|
||||
0, false, trans_pixel);
|
||||
} else if (model == null
|
||||
|| trans_pixel != model.getTransparentPixel()) {
|
||||
if (trans_pixel >= num_global_colors) {
|
||||
// Fix for 4233748: extend colormap to contain transparent pixel
|
||||
num_global_colors = trans_pixel + 1;
|
||||
global_colormap = grow_colormap(global_colormap, num_global_colors);
|
||||
}
|
||||
model = new IndexColorModel(8, num_global_colors, global_colormap,
|
||||
0, false, trans_pixel);
|
||||
global_model = model;
|
||||
}
|
||||
|
||||
// Notify the consumers
|
||||
if (first) {
|
||||
if (global_width == 0) global_width = width;
|
||||
if (global_height == 0) global_height = height;
|
||||
|
||||
setDimensions(global_width, global_height);
|
||||
setProperties(props);
|
||||
setColorModel(model);
|
||||
headerComplete();
|
||||
}
|
||||
|
||||
if (disposal_method == GifFrame.DISPOSAL_SAVE && saved_image == null) {
|
||||
saved_image = new byte[global_width * global_height];
|
||||
/*
|
||||
* If height of current image is smaller than the global height,
|
||||
* fill the gap with transparent pixels.
|
||||
*/
|
||||
if ((height < global_height) && (model != null)) {
|
||||
byte tpix = (byte)model.getTransparentPixel();
|
||||
if (tpix >= 0) {
|
||||
byte trans_rasline[] = new byte[global_width];
|
||||
for (int i=0; i<global_width;i++) {
|
||||
trans_rasline[i] = tpix;
|
||||
}
|
||||
|
||||
setPixels(0, 0, global_width, y,
|
||||
model, trans_rasline, 0, 0);
|
||||
setPixels(0, y+height, global_width,
|
||||
global_height-height-y, model, trans_rasline,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int hints = (interlace ? interlaceflags : normalflags);
|
||||
setHints(hints);
|
||||
|
||||
curframe = new GifFrame(this, disposal_method, delay,
|
||||
(curframe == null), model,
|
||||
x, y, width, height);
|
||||
|
||||
// allocate the raster data
|
||||
byte rasline[] = new byte[width];
|
||||
|
||||
if (verbose) {
|
||||
System.out.print("Reading a " + width + " by " + height + " " +
|
||||
(interlace ? "" : "non-") + "interlaced image...");
|
||||
}
|
||||
int initCodeSize = ExtractByte(block, 9);
|
||||
if (initCodeSize >= 12) {
|
||||
if (verbose) {
|
||||
System.out.println("Invalid initial code size: " +
|
||||
initCodeSize);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean ret = parseImage(x, y, width, height,
|
||||
interlace, initCodeSize,
|
||||
block, rasline, model);
|
||||
|
||||
if (!ret) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
System.out.println("done in "
|
||||
+ (System.currentTimeMillis() - tm)
|
||||
+ "ms");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] grow_colormap(byte[] colormap, int newlen) {
|
||||
byte[] newcm = new byte[newlen * 3];
|
||||
System.arraycopy(colormap, 0, newcm, 0, colormap.length);
|
||||
return newcm;
|
||||
}
|
||||
}
|
||||
|
||||
class GifFrame {
|
||||
private static final boolean verbose = false;
|
||||
private static IndexColorModel trans_model;
|
||||
|
||||
static final int DISPOSAL_NONE = 0x00;
|
||||
static final int DISPOSAL_SAVE = 0x01;
|
||||
static final int DISPOSAL_BGCOLOR = 0x02;
|
||||
static final int DISPOSAL_PREVIOUS = 0x03;
|
||||
|
||||
GifImageDecoder decoder;
|
||||
|
||||
int disposal_method;
|
||||
int delay;
|
||||
|
||||
IndexColorModel model;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
boolean initialframe;
|
||||
|
||||
public GifFrame(GifImageDecoder id, int dm, int dl, boolean init,
|
||||
IndexColorModel cm, int x, int y, int w, int h) {
|
||||
this.decoder = id;
|
||||
this.disposal_method = dm;
|
||||
this.delay = dl;
|
||||
this.model = cm;
|
||||
this.initialframe = init;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
private void setPixels(int x, int y, int w, int h,
|
||||
ColorModel cm, byte[] pix, int off, int scan) {
|
||||
decoder.setPixels(x, y, w, h, cm, pix, off, scan);
|
||||
}
|
||||
|
||||
public boolean dispose() {
|
||||
if (decoder.imageComplete(ImageConsumer.SINGLEFRAMEDONE, false) == 0) {
|
||||
return false;
|
||||
} else {
|
||||
if (delay > 0) {
|
||||
try {
|
||||
if (verbose) {
|
||||
System.out.println("sleeping: "+delay);
|
||||
}
|
||||
Thread.sleep(delay);
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
if (verbose && disposal_method != 0) {
|
||||
System.out.println("disposal method: "+disposal_method);
|
||||
}
|
||||
|
||||
int global_width = decoder.global_width;
|
||||
int global_height = decoder.global_height;
|
||||
|
||||
if (x < 0) {
|
||||
width += x;
|
||||
x = 0;
|
||||
}
|
||||
if (x + width > global_width) {
|
||||
width = global_width - x;
|
||||
}
|
||||
if (width <= 0) {
|
||||
disposal_method = DISPOSAL_NONE;
|
||||
} else {
|
||||
if (y < 0) {
|
||||
height += y;
|
||||
y = 0;
|
||||
}
|
||||
if (y + height > global_height) {
|
||||
height = global_height - y;
|
||||
}
|
||||
if (height <= 0) {
|
||||
disposal_method = DISPOSAL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (disposal_method) {
|
||||
case DISPOSAL_PREVIOUS:
|
||||
byte[] saved_image = decoder.saved_image;
|
||||
IndexColorModel saved_model = decoder.saved_model;
|
||||
if (saved_image != null) {
|
||||
setPixels(x, y, width, height,
|
||||
saved_model, saved_image,
|
||||
y * global_width + x, global_width);
|
||||
}
|
||||
break;
|
||||
case DISPOSAL_BGCOLOR:
|
||||
byte tpix;
|
||||
if (model.getTransparentPixel() < 0) {
|
||||
model = trans_model;
|
||||
if (model == null) {
|
||||
model = new IndexColorModel(8, 1,
|
||||
new byte[4], 0, true);
|
||||
trans_model = model;
|
||||
}
|
||||
tpix = 0;
|
||||
} else {
|
||||
tpix = (byte) model.getTransparentPixel();
|
||||
}
|
||||
byte[] rasline = new byte[width];
|
||||
if (tpix != 0) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
rasline[i] = tpix;
|
||||
}
|
||||
}
|
||||
|
||||
// clear saved_image using transparent pixels
|
||||
// this will be used as the background in the next display
|
||||
if( decoder.saved_image != null ) {
|
||||
for( int i = 0; i < global_width * global_height; i ++ )
|
||||
decoder.saved_image[i] = tpix;
|
||||
}
|
||||
|
||||
setPixels(x, y, width, height, model, rasline, 0, 0);
|
||||
break;
|
||||
case DISPOSAL_SAVE:
|
||||
decoder.saved_model = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
32
jdkSrc/jdk8/sun/awt/image/ImageAccessException.java
Normal file
32
jdkSrc/jdk8/sun/awt/image/ImageAccessException.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 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 sun.awt.image;
|
||||
|
||||
public class ImageAccessException extends Exception {
|
||||
public ImageAccessException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
163
jdkSrc/jdk8/sun/awt/image/ImageCache.java
Normal file
163
jdkSrc/jdk8/sun/awt/image/ImageCache.java
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2014, 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 sun.awt.image;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.ref.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.*;
|
||||
import sun.awt.AppContext;
|
||||
|
||||
/**
|
||||
* ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary
|
||||
* set of arguments. All images are held with SoftReferences so they will be
|
||||
* dropped by the GC if heap memory gets tight. When our size hits max pixel
|
||||
* count least recently requested images are removed first.
|
||||
*
|
||||
* The ImageCache must be used from the thread with an AppContext only.
|
||||
*
|
||||
*/
|
||||
final public class ImageCache {
|
||||
|
||||
// Ordered Map keyed by args hash, ordered by most recent accessed entry.
|
||||
private final LinkedHashMap<PixelsKey, ImageSoftReference> map
|
||||
= new LinkedHashMap<>(16, 0.75f, true);
|
||||
|
||||
// Maximum number of pixels to cache, this is used if maxCount
|
||||
private final int maxPixelCount;
|
||||
// The current number of pixels stored in the cache
|
||||
private int currentPixelCount = 0;
|
||||
|
||||
// Lock for concurrent access to map
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
// Reference queue for tracking lost softreferences to images in the cache
|
||||
private final ReferenceQueue<Image> referenceQueue = new ReferenceQueue<>();
|
||||
|
||||
public static ImageCache getInstance() {
|
||||
return AppContext.getSoftReferenceValue(ImageCache.class,
|
||||
() -> new ImageCache());
|
||||
}
|
||||
|
||||
ImageCache(final int maxPixelCount) {
|
||||
this.maxPixelCount = maxPixelCount;
|
||||
}
|
||||
|
||||
ImageCache() {
|
||||
this((8 * 1024 * 1024) / 4); // 8Mb of pixels
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
map.clear();
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Image getImage(final PixelsKey key){
|
||||
final ImageSoftReference ref;
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
ref = map.get(key);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
return ref == null ? null : ref.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cached image for the specified constraints.
|
||||
*
|
||||
* @param key The key with which the specified image is to be associated
|
||||
* @param image The image to store in cache
|
||||
*/
|
||||
public void setImage(final PixelsKey key, final Image image) {
|
||||
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
ImageSoftReference ref = map.get(key);
|
||||
|
||||
// check if currently in map
|
||||
if (ref != null) {
|
||||
if (ref.get() != null) {
|
||||
return;
|
||||
}
|
||||
// soft image has been removed
|
||||
currentPixelCount -= key.getPixelCount();
|
||||
map.remove(key);
|
||||
};
|
||||
|
||||
|
||||
// add new image to pixel count
|
||||
final int newPixelCount = key.getPixelCount();
|
||||
currentPixelCount += newPixelCount;
|
||||
// clean out lost references if not enough space
|
||||
if (currentPixelCount > maxPixelCount) {
|
||||
while ((ref = (ImageSoftReference)referenceQueue.poll()) != null) {
|
||||
//reference lost
|
||||
map.remove(ref.key);
|
||||
currentPixelCount -= ref.key.getPixelCount();
|
||||
}
|
||||
}
|
||||
|
||||
// remove old items till there is enough free space
|
||||
if (currentPixelCount > maxPixelCount) {
|
||||
final Iterator<Map.Entry<PixelsKey, ImageSoftReference>>
|
||||
mapIter = map.entrySet().iterator();
|
||||
while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) {
|
||||
final Map.Entry<PixelsKey, ImageSoftReference> entry =
|
||||
mapIter.next();
|
||||
mapIter.remove();
|
||||
final Image img = entry.getValue().get();
|
||||
if (img != null) img.flush();
|
||||
currentPixelCount -= entry.getValue().key.getPixelCount();
|
||||
}
|
||||
}
|
||||
|
||||
// finally put new in map
|
||||
map.put(key, new ImageSoftReference(key, image, referenceQueue));
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public interface PixelsKey {
|
||||
|
||||
int getPixelCount();
|
||||
}
|
||||
|
||||
private static class ImageSoftReference extends SoftReference<Image> {
|
||||
|
||||
final PixelsKey key;
|
||||
|
||||
ImageSoftReference(final PixelsKey key, final Image referent,
|
||||
final ReferenceQueue<? super Image> q) {
|
||||
super(referent, q);
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
94
jdkSrc/jdk8/sun/awt/image/ImageConsumerQueue.java
Normal file
94
jdkSrc/jdk8/sun/awt/image/ImageConsumerQueue.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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 sun.awt.image;
|
||||
|
||||
import java.awt.image.ImageConsumer;
|
||||
|
||||
class ImageConsumerQueue {
|
||||
ImageConsumerQueue next;
|
||||
|
||||
ImageConsumer consumer;
|
||||
boolean interested;
|
||||
|
||||
Object securityContext;
|
||||
boolean secure;
|
||||
|
||||
static ImageConsumerQueue removeConsumer(ImageConsumerQueue cqbase,
|
||||
ImageConsumer ic,
|
||||
boolean stillinterested)
|
||||
{
|
||||
ImageConsumerQueue cqprev = null;
|
||||
for (ImageConsumerQueue cq = cqbase; cq != null; cq = cq.next) {
|
||||
if (cq.consumer == ic) {
|
||||
if (cqprev == null) {
|
||||
cqbase = cq.next;
|
||||
} else {
|
||||
cqprev.next = cq.next;
|
||||
}
|
||||
cq.interested = stillinterested;
|
||||
break;
|
||||
}
|
||||
cqprev = cq;
|
||||
}
|
||||
return cqbase;
|
||||
}
|
||||
|
||||
static boolean isConsumer(ImageConsumerQueue cqbase, ImageConsumer ic) {
|
||||
for (ImageConsumerQueue cq = cqbase; cq != null; cq = cq.next) {
|
||||
if (cq.consumer == ic) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageConsumerQueue(InputStreamImageSource src, ImageConsumer ic) {
|
||||
consumer = ic;
|
||||
interested = true;
|
||||
// ImageReps do their own security at access time.
|
||||
if (ic instanceof ImageRepresentation) {
|
||||
ImageRepresentation ir = (ImageRepresentation) ic;
|
||||
if (ir.image.source != src) {
|
||||
throw new SecurityException("ImageRep added to wrong image source");
|
||||
}
|
||||
secure = true;
|
||||
} else {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
securityContext = security.getSecurityContext();
|
||||
} else {
|
||||
securityContext = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ("[" + consumer +
|
||||
", " + (interested ? "" : "not ") + "interested" +
|
||||
(securityContext != null ? ", " + securityContext : "") +
|
||||
"]");
|
||||
}
|
||||
}
|
||||
183
jdkSrc/jdk8/sun/awt/image/ImageDecoder.java
Normal file
183
jdkSrc/jdk8/sun/awt/image/ImageDecoder.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2003, 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 sun.awt.image;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.awt.image.*;
|
||||
|
||||
public abstract class ImageDecoder {
|
||||
InputStreamImageSource source;
|
||||
InputStream input;
|
||||
Thread feeder;
|
||||
|
||||
protected boolean aborted;
|
||||
protected boolean finished;
|
||||
ImageConsumerQueue queue;
|
||||
ImageDecoder next;
|
||||
|
||||
public ImageDecoder(InputStreamImageSource src, InputStream is) {
|
||||
source = src;
|
||||
input = is;
|
||||
feeder = Thread.currentThread();
|
||||
}
|
||||
|
||||
public boolean isConsumer(ImageConsumer ic) {
|
||||
return ImageConsumerQueue.isConsumer(queue, ic);
|
||||
}
|
||||
|
||||
public void removeConsumer(ImageConsumer ic) {
|
||||
queue = ImageConsumerQueue.removeConsumer(queue, ic, false);
|
||||
if (!finished && queue == null) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
protected ImageConsumerQueue nextConsumer(ImageConsumerQueue cq) {
|
||||
synchronized (source) {
|
||||
if (aborted) {
|
||||
return null;
|
||||
}
|
||||
cq = ((cq == null) ? queue : cq.next);
|
||||
while (cq != null) {
|
||||
if (cq.interested) {
|
||||
return cq;
|
||||
}
|
||||
cq = cq.next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int setDimensions(int w, int h) {
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.setDimensions(w, h);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int setProperties(Hashtable props) {
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.setProperties(props);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int setColorModel(ColorModel model) {
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.setColorModel(model);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int setHints(int hints) {
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.setHints(hints);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected void headerComplete() {
|
||||
feeder.setPriority(ImageFetcher.LOW_PRIORITY);
|
||||
}
|
||||
|
||||
protected int setPixels(int x, int y, int w, int h, ColorModel model,
|
||||
byte pix[], int off, int scansize) {
|
||||
source.latchConsumers(this);
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.setPixels(x, y, w, h, model, pix, off, scansize);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int setPixels(int x, int y, int w, int h, ColorModel model,
|
||||
int pix[], int off, int scansize) {
|
||||
source.latchConsumers(this);
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.setPixels(x, y, w, h, model, pix, off, scansize);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int imageComplete(int status, boolean done) {
|
||||
source.latchConsumers(this);
|
||||
if (done) {
|
||||
finished = true;
|
||||
source.doneDecoding(this);
|
||||
}
|
||||
ImageConsumerQueue cq = null;
|
||||
int count = 0;
|
||||
while ((cq = nextConsumer(cq)) != null) {
|
||||
cq.consumer.imageComplete(status);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public abstract void produceImage() throws IOException,
|
||||
ImageFormatException;
|
||||
|
||||
public void abort() {
|
||||
aborted = true;
|
||||
source.doneDecoding(this);
|
||||
close();
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
feeder.interrupt();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void close() {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
jdkSrc/jdk8/sun/awt/image/ImageFetchable.java
Normal file
48
jdkSrc/jdk8/sun/awt/image/ImageFetchable.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2001, 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 sun.awt.image;
|
||||
|
||||
/**
|
||||
* This interface allows the ImageFetcher class to drive the production
|
||||
* of image data in an ImageProducer class by calling the doFetch()
|
||||
* method from one of a pool of threads which are created to facilitate
|
||||
* asynchronous delivery of image data outside of the standard system
|
||||
* threads which manage the applications User Interface.
|
||||
*
|
||||
* @see ImageFetcher
|
||||
* @see ImageProducer
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
public interface ImageFetchable {
|
||||
/**
|
||||
* This method is called by one of the ImageFetcher threads to start
|
||||
* the flow of information from the ImageProducer to the ImageConsumer.
|
||||
* @see ImageFetcher
|
||||
* @see ImageProducer
|
||||
*/
|
||||
public void doFetch();
|
||||
}
|
||||
364
jdkSrc/jdk8/sun/awt/image/ImageFetcher.java
Normal file
364
jdkSrc/jdk8/sun/awt/image/ImageFetcher.java
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
|
||||
import java.util.Vector;
|
||||
import sun.awt.AppContext;
|
||||
|
||||
/**
|
||||
* An ImageFetcher is a thread used to fetch ImageFetchable objects.
|
||||
* Once an ImageFetchable object has been fetched, the ImageFetcher
|
||||
* thread may also be used to animate it if necessary, via the
|
||||
* startingAnimation() / stoppingAnimation() methods.
|
||||
*
|
||||
* There can be up to FetcherInfo.MAX_NUM_FETCHERS_PER_APPCONTEXT
|
||||
* ImageFetcher threads for each AppContext. A per-AppContext queue
|
||||
* of ImageFetchables is used to track objects to fetch.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @author Fred Ecks
|
||||
*/
|
||||
class ImageFetcher extends Thread {
|
||||
static final int HIGH_PRIORITY = 8;
|
||||
static final int LOW_PRIORITY = 3;
|
||||
static final int ANIM_PRIORITY = 2;
|
||||
|
||||
static final int TIMEOUT = 5000; // Time in milliseconds to wait for an
|
||||
// ImageFetchable to be added to the
|
||||
// queue before an ImageFetcher dies
|
||||
|
||||
/**
|
||||
* Constructor for ImageFetcher -- only called by add() below.
|
||||
*/
|
||||
private ImageFetcher(ThreadGroup threadGroup, int index) {
|
||||
super(threadGroup, "Image Fetcher " + index);
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ImageFetchable to the queue of items to fetch. Instantiates
|
||||
* a new ImageFetcher if it's reasonable to do so.
|
||||
* If there is no available fetcher to process an ImageFetchable, then
|
||||
* reports failure to caller.
|
||||
*/
|
||||
public static boolean add(ImageFetchable src) {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
synchronized(info.waitList) {
|
||||
if (!info.waitList.contains(src)) {
|
||||
info.waitList.addElement(src);
|
||||
if (info.numWaiting == 0 &&
|
||||
info.numFetchers < info.fetchers.length) {
|
||||
createFetchers(info);
|
||||
}
|
||||
/* Creation of new fetcher may fail due to high vm load
|
||||
* or some other reason.
|
||||
* If there is already exist, but busy, fetcher, we leave
|
||||
* the src in queue (it will be handled by existing
|
||||
* fetcher later).
|
||||
* Otherwise, we report failure: there is no fetcher
|
||||
* to handle the src.
|
||||
*/
|
||||
if (info.numFetchers > 0) {
|
||||
info.waitList.notify();
|
||||
} else {
|
||||
info.waitList.removeElement(src);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an ImageFetchable from the queue of items to fetch.
|
||||
*/
|
||||
public static void remove(ImageFetchable src) {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
synchronized(info.waitList) {
|
||||
if (info.waitList.contains(src)) {
|
||||
info.waitList.removeElement(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the given thread is one of the ImageFetchers.
|
||||
*/
|
||||
public static boolean isFetcher(Thread t) {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
synchronized(info.waitList) {
|
||||
for (int i = 0; i < info.fetchers.length; i++) {
|
||||
if (info.fetchers[i] == t) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the current thread is one of the ImageFetchers.
|
||||
*/
|
||||
public static boolean amFetcher() {
|
||||
return isFetcher(Thread.currentThread());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next ImageFetchable to be processed. If TIMEOUT
|
||||
* elapses in the mean time, or if the ImageFetcher is interrupted,
|
||||
* null is returned.
|
||||
*/
|
||||
private static ImageFetchable nextImage() {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
synchronized(info.waitList) {
|
||||
ImageFetchable src = null;
|
||||
long end = System.currentTimeMillis() + TIMEOUT;
|
||||
while (src == null) {
|
||||
while (info.waitList.size() == 0) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (now >= end) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
info.numWaiting++;
|
||||
info.waitList.wait(end - now);
|
||||
} catch (InterruptedException e) {
|
||||
// A normal occurrence as an AppContext is disposed
|
||||
return null;
|
||||
} finally {
|
||||
info.numWaiting--;
|
||||
}
|
||||
}
|
||||
src = (ImageFetchable) info.waitList.elementAt(0);
|
||||
info.waitList.removeElement(src);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main run() method of an ImageFetcher Thread. Calls fetchloop()
|
||||
* to do the work, then removes itself from the array of ImageFetchers.
|
||||
*/
|
||||
public void run() {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
try {
|
||||
fetchloop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
synchronized(info.waitList) {
|
||||
Thread me = Thread.currentThread();
|
||||
for (int i = 0; i < info.fetchers.length; i++) {
|
||||
if (info.fetchers[i] == me) {
|
||||
info.fetchers[i] = null;
|
||||
info.numFetchers--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main ImageFetcher loop. Repeatedly calls nextImage(), and
|
||||
* fetches the returned ImageFetchable objects until nextImage()
|
||||
* returns null.
|
||||
*/
|
||||
private void fetchloop() {
|
||||
Thread me = Thread.currentThread();
|
||||
while (isFetcher(me)) {
|
||||
// we're ignoring the return value and just clearing
|
||||
// the interrupted flag, instead of bailing out if
|
||||
// the fetcher was interrupted, as we used to,
|
||||
// because there may be other images waiting
|
||||
// to be fetched (see 4789067)
|
||||
me.interrupted();
|
||||
me.setPriority(HIGH_PRIORITY);
|
||||
ImageFetchable src = nextImage();
|
||||
if (src == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
src.doFetch();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Uncaught error fetching image:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
stoppingAnimation(me);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recycles this ImageFetcher thread as an image animator thread.
|
||||
* Removes this ImageFetcher from the array of ImageFetchers, and
|
||||
* resets the thread name to "ImageAnimator".
|
||||
*/
|
||||
static void startingAnimation() {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
Thread me = Thread.currentThread();
|
||||
synchronized(info.waitList) {
|
||||
for (int i = 0; i < info.fetchers.length; i++) {
|
||||
if (info.fetchers[i] == me) {
|
||||
info.fetchers[i] = null;
|
||||
info.numFetchers--;
|
||||
me.setName("Image Animator " + i);
|
||||
if(info.waitList.size() > info.numWaiting) {
|
||||
createFetchers(info);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
me.setPriority(ANIM_PRIORITY);
|
||||
me.setName("Image Animator");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this image animator thread back to service as an ImageFetcher
|
||||
* if possible. Puts it back into the array of ImageFetchers and sets
|
||||
* the thread name back to "Image Fetcher". If there are already the
|
||||
* maximum number of ImageFetchers, this method simply returns, and
|
||||
* fetchloop() will drop out when it sees that this thread isn't one of
|
||||
* the ImageFetchers, and this thread will die.
|
||||
*/
|
||||
private static void stoppingAnimation(Thread me) {
|
||||
final FetcherInfo info = FetcherInfo.getFetcherInfo();
|
||||
synchronized(info.waitList) {
|
||||
int index = -1;
|
||||
for (int i = 0; i < info.fetchers.length; i++) {
|
||||
if (info.fetchers[i] == me) {
|
||||
return;
|
||||
}
|
||||
if (info.fetchers[i] == null) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
if (index >= 0) {
|
||||
info.fetchers[index] = me;
|
||||
info.numFetchers++;
|
||||
me.setName("Image Fetcher " + index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and start ImageFetcher threads in the appropriate ThreadGroup.
|
||||
*/
|
||||
private static void createFetchers(final FetcherInfo info) {
|
||||
// We need to instantiate a new ImageFetcher thread.
|
||||
// First, figure out which ThreadGroup we'll put the
|
||||
// new ImageFetcher into
|
||||
final AppContext appContext = AppContext.getAppContext();
|
||||
ThreadGroup threadGroup = appContext.getThreadGroup();
|
||||
ThreadGroup fetcherThreadGroup;
|
||||
try {
|
||||
if (threadGroup.getParent() != null) {
|
||||
// threadGroup is not the root, so we proceed
|
||||
fetcherThreadGroup = threadGroup;
|
||||
} else {
|
||||
// threadGroup is the root ("system") ThreadGroup.
|
||||
// We instead want to use its child: the "main"
|
||||
// ThreadGroup. Thus, we start with the current
|
||||
// ThreadGroup, and go up the tree until
|
||||
// threadGroup.getParent().getParent() == null.
|
||||
threadGroup = Thread.currentThread().getThreadGroup();
|
||||
ThreadGroup parent = threadGroup.getParent();
|
||||
while ((parent != null)
|
||||
&& (parent.getParent() != null)) {
|
||||
threadGroup = parent;
|
||||
parent = threadGroup.getParent();
|
||||
}
|
||||
fetcherThreadGroup = threadGroup;
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// Not allowed access to parent ThreadGroup -- just use
|
||||
// the AppContext's ThreadGroup
|
||||
fetcherThreadGroup = appContext.getThreadGroup();
|
||||
}
|
||||
final ThreadGroup fetcherGroup = fetcherThreadGroup;
|
||||
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
for (int i = 0; i < info.fetchers.length; i++) {
|
||||
if (info.fetchers[i] == null) {
|
||||
ImageFetcher f = new ImageFetcher(
|
||||
fetcherGroup, i);
|
||||
try {
|
||||
f.start();
|
||||
info.fetchers[i] = f;
|
||||
info.numFetchers++;
|
||||
break;
|
||||
} catch (Error e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The FetcherInfo class encapsulates the per-AppContext ImageFetcher
|
||||
* information. This includes the array of ImageFetchers, as well as
|
||||
* the queue of ImageFetchable objects.
|
||||
*/
|
||||
class FetcherInfo {
|
||||
static final int MAX_NUM_FETCHERS_PER_APPCONTEXT = 4;
|
||||
|
||||
Thread[] fetchers;
|
||||
int numFetchers;
|
||||
int numWaiting;
|
||||
Vector waitList;
|
||||
|
||||
private FetcherInfo() {
|
||||
fetchers = new Thread[MAX_NUM_FETCHERS_PER_APPCONTEXT];
|
||||
numFetchers = 0;
|
||||
numWaiting = 0;
|
||||
waitList = new Vector();
|
||||
}
|
||||
|
||||
/* The key to put()/get() the FetcherInfo into/from the AppContext. */
|
||||
private static final Object FETCHER_INFO_KEY =
|
||||
new StringBuffer("FetcherInfo");
|
||||
|
||||
static FetcherInfo getFetcherInfo() {
|
||||
AppContext appContext = AppContext.getAppContext();
|
||||
synchronized(appContext) {
|
||||
FetcherInfo info = (FetcherInfo)appContext.get(FETCHER_INFO_KEY);
|
||||
if (info == null) {
|
||||
info = new FetcherInfo();
|
||||
appContext.put(FETCHER_INFO_KEY, info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
jdkSrc/jdk8/sun/awt/image/ImageFormatException.java
Normal file
32
jdkSrc/jdk8/sun/awt/image/ImageFormatException.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 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 sun.awt.image;
|
||||
|
||||
public class ImageFormatException extends Exception {
|
||||
public ImageFormatException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
951
jdkSrc/jdk8/sun/awt/image/ImageRepresentation.java
Normal file
951
jdkSrc/jdk8/sun/awt/image/ImageRepresentation.java
Normal file
@@ -0,0 +1,951 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.ImageConsumer;
|
||||
import java.awt.image.ImageObserver;
|
||||
import sun.awt.image.ByteComponentRaster;
|
||||
import sun.awt.image.IntegerComponentRaster;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import sun.awt.image.ImageWatched;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class ImageRepresentation extends ImageWatched implements ImageConsumer
|
||||
{
|
||||
InputStreamImageSource src;
|
||||
ToolkitImage image;
|
||||
int tag;
|
||||
|
||||
long pData; // used by windows native code only -- internal state REMIND ATTN @@
|
||||
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
int hints;
|
||||
|
||||
int availinfo;
|
||||
|
||||
Rectangle newbits;
|
||||
|
||||
BufferedImage bimage;
|
||||
WritableRaster biRaster;
|
||||
protected ColorModel cmodel;
|
||||
ColorModel srcModel = null;
|
||||
int[] srcLUT = null;
|
||||
int srcLUTtransIndex = -1;
|
||||
int numSrcLUT = 0;
|
||||
boolean forceCMhint;
|
||||
int sstride;
|
||||
boolean isDefaultBI = false;
|
||||
boolean isSameCM = false;
|
||||
|
||||
private native static void initIDs();
|
||||
|
||||
static {
|
||||
/* ensure that the necessary native libraries are loaded */
|
||||
NativeLibLoader.loadLibraries();
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ImageRepresentation for the given Image. The
|
||||
* width and height are unknown at this point. The color
|
||||
* model is a hint as to the color model to use when creating
|
||||
* the buffered image. If null, the src color model will
|
||||
* be used.
|
||||
*/
|
||||
public ImageRepresentation(ToolkitImage im, ColorModel cmodel, boolean
|
||||
forceCMhint) {
|
||||
image = im;
|
||||
|
||||
if (image.getSource() instanceof InputStreamImageSource) {
|
||||
src = (InputStreamImageSource) image.getSource();
|
||||
}
|
||||
|
||||
setColorModel(cmodel);
|
||||
|
||||
this.forceCMhint = forceCMhint;
|
||||
}
|
||||
|
||||
/* REMIND: Only used for Frame.setIcon - should use ImageWatcher instead */
|
||||
public synchronized void reconstruct(int flags) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
int missinginfo = flags & ~availinfo;
|
||||
if ((availinfo & ImageObserver.ERROR) == 0 && missinginfo != 0) {
|
||||
numWaiters++;
|
||||
try {
|
||||
startProduction();
|
||||
missinginfo = flags & ~availinfo;
|
||||
while ((availinfo & ImageObserver.ERROR) == 0 &&
|
||||
missinginfo != 0)
|
||||
{
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
missinginfo = flags & ~availinfo;
|
||||
}
|
||||
} finally {
|
||||
decrementWaiters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setDimensions(int w, int h) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
|
||||
image.setDimensions(w, h);
|
||||
|
||||
newInfo(image, (ImageObserver.WIDTH | ImageObserver.HEIGHT),
|
||||
0, 0, w, h);
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
imageComplete(ImageConsumer.IMAGEERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (width != w || height != h) {
|
||||
// dimension mismatch => trigger recreation of the buffer
|
||||
bimage = null;
|
||||
}
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
availinfo |= ImageObserver.WIDTH | ImageObserver.HEIGHT;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
ColorModel getColorModel() {
|
||||
return cmodel;
|
||||
}
|
||||
|
||||
BufferedImage getBufferedImage() {
|
||||
return bimage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BufferedImage that will be used as the representation of
|
||||
* the pixel data. Subclasses can override this method to return
|
||||
* platform specific subclasses of BufferedImage that may or may not be
|
||||
* accelerated.
|
||||
*
|
||||
* It is subclass' responsibility to propagate acceleration priority
|
||||
* to the newly created image.
|
||||
*/
|
||||
protected BufferedImage createImage(ColorModel cm,
|
||||
WritableRaster raster,
|
||||
boolean isRasterPremultiplied,
|
||||
Hashtable properties)
|
||||
{
|
||||
BufferedImage bi =
|
||||
new BufferedImage(cm, raster, isRasterPremultiplied, null);
|
||||
bi.setAccelerationPriority(image.getAccelerationPriority());
|
||||
return bi;
|
||||
}
|
||||
|
||||
public void setProperties(Hashtable<?,?> props) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
image.setProperties(props);
|
||||
newInfo(image, ImageObserver.PROPERTIES, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void setColorModel(ColorModel model) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
srcModel = model;
|
||||
|
||||
// Check to see if model is INT_RGB
|
||||
if (model instanceof IndexColorModel) {
|
||||
if (model.getTransparency() == model.TRANSLUCENT) {
|
||||
// REMIND:
|
||||
// Probably need to composite anyway so force ARGB
|
||||
cmodel = ColorModel.getRGBdefault();
|
||||
srcLUT = null;
|
||||
}
|
||||
else {
|
||||
IndexColorModel icm = (IndexColorModel) model;
|
||||
numSrcLUT = icm.getMapSize();
|
||||
srcLUT = new int[Math.max(numSrcLUT, 256)];
|
||||
icm.getRGBs(srcLUT);
|
||||
srcLUTtransIndex = icm.getTransparentPixel();
|
||||
cmodel = model;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (cmodel == null) {
|
||||
cmodel = model;
|
||||
srcLUT = null;
|
||||
}
|
||||
else if (model instanceof DirectColorModel) {
|
||||
// If it is INT_RGB or INT_ARGB, use the model
|
||||
DirectColorModel dcm = (DirectColorModel) model;
|
||||
if ((dcm.getRedMask() == 0xff0000) &&
|
||||
(dcm.getGreenMask() == 0xff00) &&
|
||||
(dcm.getBlueMask() == 0x00ff)) {
|
||||
cmodel = model;
|
||||
srcLUT = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isSameCM = (cmodel == model);
|
||||
}
|
||||
|
||||
void createBufferedImage() {
|
||||
// REMIND: Be careful! Is this called everytime there is a
|
||||
// startProduction? We only want to call it if it is new or
|
||||
// there is an error
|
||||
isDefaultBI = false;
|
||||
try {
|
||||
biRaster = cmodel.createCompatibleWritableRaster(width, height);
|
||||
bimage = createImage(cmodel, biRaster,
|
||||
cmodel.isAlphaPremultiplied(), null);
|
||||
} catch (Exception e) {
|
||||
// Create a default image
|
||||
cmodel = ColorModel.getRGBdefault();
|
||||
biRaster = cmodel.createCompatibleWritableRaster(width, height);
|
||||
bimage = createImage(cmodel, biRaster, false, null);
|
||||
}
|
||||
int type = bimage.getType();
|
||||
|
||||
if ((cmodel == ColorModel.getRGBdefault()) ||
|
||||
(type == BufferedImage.TYPE_INT_RGB) ||
|
||||
(type == BufferedImage.TYPE_INT_ARGB_PRE)) {
|
||||
isDefaultBI = true;
|
||||
}
|
||||
else if (cmodel instanceof DirectColorModel) {
|
||||
DirectColorModel dcm = (DirectColorModel) cmodel;
|
||||
if (dcm.getRedMask() == 0xff0000 &&
|
||||
dcm.getGreenMask() == 0xff00 &&
|
||||
dcm.getBlueMask() == 0xff) {
|
||||
isDefaultBI = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void convertToRGB() {
|
||||
int w = bimage.getWidth();
|
||||
int h = bimage.getHeight();
|
||||
int size = w*h;
|
||||
|
||||
DataBufferInt dbi = new DataBufferInt(size);
|
||||
// Note that stealData() requires a markDirty() afterwards
|
||||
// since we modify the data in it.
|
||||
int newpixels[] = SunWritableRaster.stealData(dbi, 0);
|
||||
if (cmodel instanceof IndexColorModel &&
|
||||
biRaster instanceof ByteComponentRaster &&
|
||||
biRaster.getNumDataElements() == 1)
|
||||
{
|
||||
ByteComponentRaster bct = (ByteComponentRaster) biRaster;
|
||||
byte[] data = bct.getDataStorage();
|
||||
int coff = bct.getDataOffset(0);
|
||||
for (int i=0; i < size; i++) {
|
||||
newpixels[i] = srcLUT[data[coff+i]&0xff];
|
||||
}
|
||||
}
|
||||
else {
|
||||
Object srcpixels = null;
|
||||
int off=0;
|
||||
for (int y=0; y < h; y++) {
|
||||
for (int x=0; x < w; x++) {
|
||||
srcpixels=biRaster.getDataElements(x, y, srcpixels);
|
||||
newpixels[off++] = cmodel.getRGB(srcpixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We modified the data array directly above so mark it as dirty now...
|
||||
SunWritableRaster.markDirty(dbi);
|
||||
|
||||
isSameCM = false;
|
||||
cmodel = ColorModel.getRGBdefault();
|
||||
|
||||
int bandMasks[] = {0x00ff0000,
|
||||
0x0000ff00,
|
||||
0x000000ff,
|
||||
0xff000000};
|
||||
|
||||
biRaster = Raster.createPackedRaster(dbi,w,h,w,
|
||||
bandMasks,null);
|
||||
|
||||
bimage = createImage(cmodel, biRaster,
|
||||
cmodel.isAlphaPremultiplied(), null);
|
||||
srcLUT = null;
|
||||
isDefaultBI = true;
|
||||
}
|
||||
|
||||
public void setHints(int h) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
hints = h;
|
||||
}
|
||||
|
||||
private native boolean setICMpixels(int x, int y, int w, int h, int[] lut,
|
||||
byte[] pix, int off, int scansize,
|
||||
IntegerComponentRaster ict);
|
||||
private native boolean setDiffICM(int x, int y, int w, int h, int[] lut,
|
||||
int transPix, int numLut, IndexColorModel icm,
|
||||
byte[] pix, int off, int scansize,
|
||||
ByteComponentRaster bct, int chanOff);
|
||||
static boolean s_useNative = true;
|
||||
|
||||
public void setPixels(int x, int y, int w, int h,
|
||||
ColorModel model,
|
||||
byte pix[], int off, int scansize) {
|
||||
int lineOff=off;
|
||||
int poff;
|
||||
int[] newLUT=null;
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
|
||||
// REMIND: What if the model doesn't fit in default color model?
|
||||
synchronized (this) {
|
||||
if (bimage == null) {
|
||||
if (cmodel == null) {
|
||||
cmodel = model;
|
||||
}
|
||||
createBufferedImage();
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int biWidth = biRaster.getWidth();
|
||||
int biHeight = biRaster.getHeight();
|
||||
|
||||
int x1 = x+w; // Overflow protection below
|
||||
int y1 = y+h; // Overflow protection below
|
||||
if (x < 0) {
|
||||
off -= x;
|
||||
x = 0;
|
||||
} else if (x1 < 0) {
|
||||
x1 = biWidth; // Must be overflow
|
||||
}
|
||||
if (y < 0) {
|
||||
off -= y*scansize;
|
||||
y = 0;
|
||||
} else if (y1 < 0) {
|
||||
y1 = biHeight; // Must be overflow
|
||||
}
|
||||
if (x1 > biWidth) {
|
||||
x1 = biWidth;
|
||||
}
|
||||
if (y1 > biHeight) {
|
||||
y1 = biHeight;
|
||||
}
|
||||
if (x >= x1 || y >= y1) {
|
||||
return;
|
||||
}
|
||||
// x,y,x1,y1 are all >= 0, so w,h must be >= 0
|
||||
w = x1-x;
|
||||
h = y1-y;
|
||||
// off is first pixel read so it must be in bounds
|
||||
if (off < 0 || off >= pix.length) {
|
||||
// They overflowed their own array
|
||||
throw new ArrayIndexOutOfBoundsException("Data offset out of bounds.");
|
||||
}
|
||||
// pix.length and off are >= 0 so remainder >= 0
|
||||
int remainder = pix.length - off;
|
||||
if (remainder < w) {
|
||||
// They overflowed their own array
|
||||
throw new ArrayIndexOutOfBoundsException("Data array is too short.");
|
||||
}
|
||||
int num;
|
||||
if (scansize < 0) {
|
||||
num = (off / -scansize) + 1;
|
||||
} else if (scansize > 0) {
|
||||
num = ((remainder-w) / scansize) + 1;
|
||||
} else {
|
||||
num = h;
|
||||
}
|
||||
if (h > num) {
|
||||
// They overflowed their own array.
|
||||
throw new ArrayIndexOutOfBoundsException("Data array is too short.");
|
||||
}
|
||||
|
||||
if (isSameCM && (cmodel != model) && (srcLUT != null) &&
|
||||
(model instanceof IndexColorModel) &&
|
||||
(biRaster instanceof ByteComponentRaster))
|
||||
{
|
||||
IndexColorModel icm = (IndexColorModel) model;
|
||||
ByteComponentRaster bct = (ByteComponentRaster) biRaster;
|
||||
int numlut = numSrcLUT;
|
||||
if (!setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
|
||||
numSrcLUT, icm,
|
||||
pix, off, scansize, bct,
|
||||
bct.getDataOffset(0))) {
|
||||
convertToRGB();
|
||||
}
|
||||
else {
|
||||
// Note that setDiffICM modified the raster directly
|
||||
// so we must mark it as changed
|
||||
bct.markDirty();
|
||||
if (numlut != numSrcLUT) {
|
||||
boolean hasAlpha = icm.hasAlpha();
|
||||
if (srcLUTtransIndex != -1) {
|
||||
hasAlpha = true;
|
||||
}
|
||||
int nbits = icm.getPixelSize();
|
||||
icm = new IndexColorModel(nbits,
|
||||
numSrcLUT, srcLUT,
|
||||
0, hasAlpha,
|
||||
srcLUTtransIndex,
|
||||
(nbits > 8
|
||||
? DataBuffer.TYPE_USHORT
|
||||
: DataBuffer.TYPE_BYTE));
|
||||
cmodel = icm;
|
||||
bimage = createImage(icm, bct, false, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefaultBI) {
|
||||
int pixel;
|
||||
IntegerComponentRaster iraster =
|
||||
(IntegerComponentRaster) biRaster;
|
||||
if (srcLUT != null && model instanceof IndexColorModel) {
|
||||
if (model != srcModel) {
|
||||
// Fill in the new lut
|
||||
((IndexColorModel)model).getRGBs(srcLUT);
|
||||
srcModel = model;
|
||||
}
|
||||
|
||||
if (s_useNative) {
|
||||
// Note that setICMpixels modifies the raster directly
|
||||
// so we must mark it as changed afterwards
|
||||
if (setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
|
||||
iraster))
|
||||
{
|
||||
iraster.markDirty();
|
||||
} else {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int[] storage = new int[w*h];
|
||||
int soff = 0;
|
||||
// It is an IndexColorModel
|
||||
for (int yoff=0; yoff < h; yoff++,
|
||||
lineOff += scansize) {
|
||||
poff = lineOff;
|
||||
for (int i=0; i < w; i++) {
|
||||
storage[soff++] = srcLUT[pix[poff++]&0xff];
|
||||
}
|
||||
}
|
||||
iraster.setDataElements(x, y, w, h, storage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int[] storage = new int[w];
|
||||
for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
|
||||
poff = lineOff;
|
||||
for (int i=0; i < w; i++) {
|
||||
storage[i] = model.getRGB(pix[poff++]&0xff);
|
||||
}
|
||||
iraster.setDataElements(x, yoff, w, 1, storage);
|
||||
}
|
||||
availinfo |= ImageObserver.SOMEBITS;
|
||||
}
|
||||
}
|
||||
else if ((cmodel == model) &&
|
||||
(biRaster instanceof ByteComponentRaster) &&
|
||||
(biRaster.getNumDataElements() == 1)){
|
||||
ByteComponentRaster bt = (ByteComponentRaster) biRaster;
|
||||
if (off == 0 && scansize == w) {
|
||||
bt.putByteData(x, y, w, h, pix);
|
||||
}
|
||||
else {
|
||||
byte[] bpix = new byte[w];
|
||||
poff = off;
|
||||
for (int yoff=y; yoff < y+h; yoff++) {
|
||||
System.arraycopy(pix, poff, bpix, 0, w);
|
||||
bt.putByteData(x, yoff, w, 1, bpix);
|
||||
poff += scansize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
|
||||
poff = lineOff;
|
||||
for (int xoff=x; xoff < x+w; xoff++) {
|
||||
bimage.setRGB(xoff, yoff,
|
||||
model.getRGB(pix[poff++]&0xff));
|
||||
}
|
||||
}
|
||||
availinfo |= ImageObserver.SOMEBITS;
|
||||
}
|
||||
}
|
||||
|
||||
if ((availinfo & ImageObserver.FRAMEBITS) == 0) {
|
||||
newInfo(image, ImageObserver.SOMEBITS, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setPixels(int x, int y, int w, int h, ColorModel model,
|
||||
int pix[], int off, int scansize)
|
||||
{
|
||||
int lineOff=off;
|
||||
int poff;
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
|
||||
// REMIND: What if the model doesn't fit in default color model?
|
||||
synchronized (this) {
|
||||
if (bimage == null) {
|
||||
if (cmodel == null) {
|
||||
cmodel = model;
|
||||
}
|
||||
createBufferedImage();
|
||||
}
|
||||
|
||||
int[] storage = new int[w];
|
||||
int yoff;
|
||||
int pixel;
|
||||
|
||||
if (cmodel instanceof IndexColorModel) {
|
||||
// REMIND: Right now we don't support writing back into ICM
|
||||
// images.
|
||||
convertToRGB();
|
||||
}
|
||||
|
||||
if ((model == cmodel) &&
|
||||
(biRaster instanceof IntegerComponentRaster)) {
|
||||
IntegerComponentRaster iraster =
|
||||
(IntegerComponentRaster) biRaster;
|
||||
|
||||
if (off == 0 && scansize == w) {
|
||||
iraster.setDataElements(x, y, w, h, pix);
|
||||
}
|
||||
else {
|
||||
// Need to pack the data
|
||||
for (yoff=y; yoff < y+h; yoff++, lineOff+=scansize) {
|
||||
System.arraycopy(pix, lineOff, storage, 0, w);
|
||||
iraster.setDataElements(x, yoff, w, 1, storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (model.getTransparency() != model.OPAQUE &&
|
||||
cmodel.getTransparency() == cmodel.OPAQUE) {
|
||||
convertToRGB();
|
||||
}
|
||||
|
||||
if (isDefaultBI) {
|
||||
IntegerComponentRaster iraster =
|
||||
(IntegerComponentRaster) biRaster;
|
||||
int[] data = iraster.getDataStorage();
|
||||
if (cmodel.equals(model)) {
|
||||
int sstride = iraster.getScanlineStride();
|
||||
int doff = y*sstride + x;
|
||||
for (yoff=0; yoff < h; yoff++, lineOff += scansize) {
|
||||
System.arraycopy(pix, lineOff, data, doff, w);
|
||||
doff += sstride;
|
||||
}
|
||||
// Note: manual modification of pixels, mark the
|
||||
// raster as changed
|
||||
iraster.markDirty();
|
||||
}
|
||||
else {
|
||||
for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
|
||||
poff = lineOff;
|
||||
for (int i=0; i < w; i++) {
|
||||
storage[i]=model.getRGB(pix[poff++]);
|
||||
}
|
||||
iraster.setDataElements(x, yoff, w, 1, storage);
|
||||
}
|
||||
}
|
||||
|
||||
availinfo |= ImageObserver.SOMEBITS;
|
||||
}
|
||||
else {
|
||||
Object tmp = null;
|
||||
|
||||
for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
|
||||
poff = lineOff;
|
||||
for (int xoff=x; xoff < x+w; xoff++) {
|
||||
pixel = model.getRGB(pix[poff++]);
|
||||
tmp = cmodel.getDataElements(pixel,tmp);
|
||||
biRaster.setDataElements(xoff, yoff,tmp);
|
||||
}
|
||||
}
|
||||
availinfo |= ImageObserver.SOMEBITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can't do this here since we might need to transform/clip
|
||||
// the region
|
||||
if (((availinfo & ImageObserver.FRAMEBITS) == 0)) {
|
||||
newInfo(image, ImageObserver.SOMEBITS, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getOpaqueRGBImage() {
|
||||
if (bimage.getType() == BufferedImage.TYPE_INT_ARGB) {
|
||||
int w = bimage.getWidth();
|
||||
int h = bimage.getHeight();
|
||||
int size = w * h;
|
||||
|
||||
// Note that we steal the data array here, but only for reading...
|
||||
DataBufferInt db = (DataBufferInt)biRaster.getDataBuffer();
|
||||
int[] pixels = SunWritableRaster.stealData(db, 0);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if ((pixels[i] >>> 24) != 0xff) {
|
||||
return bimage;
|
||||
}
|
||||
}
|
||||
|
||||
ColorModel opModel = new DirectColorModel(24,
|
||||
0x00ff0000,
|
||||
0x0000ff00,
|
||||
0x000000ff);
|
||||
|
||||
int bandmasks[] = {0x00ff0000, 0x0000ff00, 0x000000ff};
|
||||
WritableRaster opRaster = Raster.createPackedRaster(db, w, h, w,
|
||||
bandmasks,
|
||||
null);
|
||||
|
||||
try {
|
||||
BufferedImage opImage = createImage(opModel, opRaster,
|
||||
false, null);
|
||||
return opImage;
|
||||
} catch (Exception e) {
|
||||
return bimage;
|
||||
}
|
||||
}
|
||||
return bimage;
|
||||
}
|
||||
|
||||
private boolean consuming = false;
|
||||
|
||||
public void imageComplete(int status) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
boolean done;
|
||||
int info;
|
||||
switch (status) {
|
||||
default:
|
||||
case ImageConsumer.IMAGEABORTED:
|
||||
done = true;
|
||||
info = ImageObserver.ABORT;
|
||||
break;
|
||||
case ImageConsumer.IMAGEERROR:
|
||||
image.addInfo(ImageObserver.ERROR);
|
||||
done = true;
|
||||
info = ImageObserver.ERROR;
|
||||
dispose();
|
||||
break;
|
||||
case ImageConsumer.STATICIMAGEDONE:
|
||||
done = true;
|
||||
info = ImageObserver.ALLBITS;
|
||||
break;
|
||||
case ImageConsumer.SINGLEFRAMEDONE:
|
||||
done = false;
|
||||
info = ImageObserver.FRAMEBITS;
|
||||
break;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (done) {
|
||||
image.getSource().removeConsumer(this);
|
||||
consuming = false;
|
||||
newbits = null;
|
||||
|
||||
if (bimage != null) {
|
||||
bimage = getOpaqueRGBImage();
|
||||
}
|
||||
}
|
||||
availinfo |= info;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
newInfo(image, info, 0, 0, width, height);
|
||||
|
||||
image.infoDone(status);
|
||||
}
|
||||
|
||||
/*synchronized*/ void startProduction() {
|
||||
if (!consuming) {
|
||||
consuming = true;
|
||||
image.getSource().startProduction(this);
|
||||
}
|
||||
}
|
||||
|
||||
private int numWaiters;
|
||||
|
||||
private synchronized void checkConsumption() {
|
||||
if (isWatcherListEmpty() && numWaiters == 0 &&
|
||||
((availinfo & ImageObserver.ALLBITS) == 0))
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void notifyWatcherListEmpty() {
|
||||
checkConsumption();
|
||||
}
|
||||
|
||||
private synchronized void decrementWaiters() {
|
||||
--numWaiters;
|
||||
checkConsumption();
|
||||
}
|
||||
|
||||
public boolean prepare(ImageObserver iw) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
if (iw != null) {
|
||||
iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
|
||||
-1, -1, -1, -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
if (!done) {
|
||||
addWatcher(iw);
|
||||
startProduction();
|
||||
// Some producers deliver image data synchronously
|
||||
done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
public int check(ImageObserver iw) {
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & (ImageObserver.ERROR | ImageObserver.ALLBITS)) == 0) {
|
||||
addWatcher(iw);
|
||||
}
|
||||
|
||||
return availinfo;
|
||||
}
|
||||
|
||||
public boolean drawToBufImage(Graphics g, ToolkitImage img,
|
||||
int x, int y, Color bg,
|
||||
ImageObserver iw) {
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
if (iw != null) {
|
||||
iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
|
||||
-1, -1, -1, -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
|
||||
|
||||
if (!done && !abort) {
|
||||
addWatcher(iw);
|
||||
startProduction();
|
||||
// Some producers deliver image data synchronously
|
||||
done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
}
|
||||
|
||||
if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
|
||||
g.drawImage (bimage, x, y, bg, null);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
public boolean drawToBufImage(Graphics g, ToolkitImage img,
|
||||
int x, int y, int w, int h,
|
||||
Color bg, ImageObserver iw) {
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
if (iw != null) {
|
||||
iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
|
||||
-1, -1, -1, -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
|
||||
|
||||
if (!done && !abort) {
|
||||
addWatcher(iw);
|
||||
startProduction();
|
||||
// Some producers deliver image data synchronously
|
||||
done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
}
|
||||
|
||||
if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
|
||||
g.drawImage (bimage, x, y, w, h, bg, null);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
public boolean drawToBufImage(Graphics g, ToolkitImage img,
|
||||
int dx1, int dy1, int dx2, int dy2,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bg, ImageObserver iw) {
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
if (iw != null) {
|
||||
iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
|
||||
-1, -1, -1, -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
|
||||
|
||||
if (!done && !abort) {
|
||||
addWatcher(iw);
|
||||
startProduction();
|
||||
// Some producers deliver image data synchronously
|
||||
done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
}
|
||||
|
||||
if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
|
||||
g.drawImage (bimage,
|
||||
dx1, dy1, dx2, dy2,
|
||||
sx1, sy1, sx2, sy2,
|
||||
bg, null);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
public boolean drawToBufImage(Graphics g, ToolkitImage img,
|
||||
AffineTransform xform,
|
||||
ImageObserver iw)
|
||||
{
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
if (iw != null) {
|
||||
iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
|
||||
-1, -1, -1, -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
|
||||
|
||||
if (!done && !abort) {
|
||||
addWatcher(iw);
|
||||
startProduction();
|
||||
// Some producers deliver image data synchronously
|
||||
done = ((availinfo & ImageObserver.ALLBITS) != 0);
|
||||
}
|
||||
|
||||
if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
|
||||
g2.drawImage (bimage, xform, null);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
synchronized void abort() {
|
||||
image.getSource().removeConsumer(this);
|
||||
consuming = false;
|
||||
newbits = null;
|
||||
bimage = null;
|
||||
biRaster = null;
|
||||
cmodel = null;
|
||||
srcLUT = null;
|
||||
isDefaultBI = false;
|
||||
isSameCM = false;
|
||||
|
||||
newInfo(image, ImageObserver.ABORT, -1, -1, -1, -1);
|
||||
availinfo &= ~(ImageObserver.SOMEBITS
|
||||
| ImageObserver.FRAMEBITS
|
||||
| ImageObserver.ALLBITS
|
||||
| ImageObserver.ERROR);
|
||||
}
|
||||
|
||||
synchronized void dispose() {
|
||||
image.getSource().removeConsumer(this);
|
||||
consuming = false;
|
||||
newbits = null;
|
||||
availinfo &= ~(ImageObserver.SOMEBITS
|
||||
| ImageObserver.FRAMEBITS
|
||||
| ImageObserver.ALLBITS);
|
||||
}
|
||||
|
||||
public void setAccelerationPriority(float priority) {
|
||||
if (bimage != null) {
|
||||
bimage.setAccelerationPriority(priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
204
jdkSrc/jdk8/sun/awt/image/ImageWatched.java
Normal file
204
jdkSrc/jdk8/sun/awt/image/ImageWatched.java
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2012, 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 sun.awt.image;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.ImageObserver;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
public abstract class ImageWatched {
|
||||
public static Link endlink = new Link();
|
||||
|
||||
public Link watcherList;
|
||||
|
||||
public ImageWatched() {
|
||||
watcherList = endlink;
|
||||
}
|
||||
|
||||
/*
|
||||
* This class defines a node on a linked list of ImageObservers.
|
||||
* The base class defines the dummy implementation used for the
|
||||
* last link on all chains and a subsequent subclass then
|
||||
* defines the standard implementation that manages a weak
|
||||
* reference to a real ImageObserver.
|
||||
*/
|
||||
public static class Link {
|
||||
/*
|
||||
* Check if iw is the referent of this Link or any
|
||||
* subsequent Link objects on this chain.
|
||||
*/
|
||||
public boolean isWatcher(ImageObserver iw) {
|
||||
return false; // No "iw" down here.
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove this Link from the chain if its referent
|
||||
* is the indicated target or if it has been nulled
|
||||
* out by the garbage collector.
|
||||
* Return the new remainder of the chain.
|
||||
* The argument may be null which will trigger
|
||||
* the chain to remove only the dead (null) links.
|
||||
* This method is only ever called inside a
|
||||
* synchronized block so Link.next modifications
|
||||
* will be safe.
|
||||
*/
|
||||
public Link removeWatcher(ImageObserver iw) {
|
||||
return this; // Leave me as the end link.
|
||||
}
|
||||
|
||||
/*
|
||||
* Deliver the indicated image update information
|
||||
* to the referent of this Link and return a boolean
|
||||
* indicating whether or not some referent became
|
||||
* null or has indicated a lack of interest in
|
||||
* further updates to its imageUpdate() method.
|
||||
* This method is not called inside a synchronized
|
||||
* block so Link.next modifications are not safe.
|
||||
*/
|
||||
public boolean newInfo(Image img, int info,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
return false; // No disinterested parties down here.
|
||||
}
|
||||
}
|
||||
|
||||
static class AccWeakReference<T> extends WeakReference<T> {
|
||||
|
||||
private final AccessControlContext acc;
|
||||
|
||||
AccWeakReference(T ref) {
|
||||
super(ref);
|
||||
acc = AccessController.getContext();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard Link implementation to manage a Weak Reference
|
||||
* to an ImageObserver.
|
||||
*/
|
||||
public static class WeakLink extends Link {
|
||||
private final AccWeakReference<ImageObserver> myref;
|
||||
private Link next;
|
||||
|
||||
public WeakLink(ImageObserver obs, Link next) {
|
||||
myref = new AccWeakReference<ImageObserver>(obs);
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public boolean isWatcher(ImageObserver iw) {
|
||||
return (myref.get() == iw || next.isWatcher(iw));
|
||||
}
|
||||
|
||||
public Link removeWatcher(ImageObserver iw) {
|
||||
ImageObserver myiw = myref.get();
|
||||
if (myiw == null) {
|
||||
// Remove me from the chain, but continue recursion.
|
||||
return next.removeWatcher(iw);
|
||||
}
|
||||
// At this point myiw is not null so we know this test will
|
||||
// never succeed if this is a pruning pass (iw == null).
|
||||
if (myiw == iw) {
|
||||
// Remove me from the chain and end the recursion here.
|
||||
return next;
|
||||
}
|
||||
// I am alive, but not the one to be removed, recurse
|
||||
// and update my next link and leave me in the chain.
|
||||
next = next.removeWatcher(iw);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static boolean update(ImageObserver iw, AccessControlContext acc,
|
||||
Image img, int info,
|
||||
int x, int y, int w, int h) {
|
||||
|
||||
if (acc != null || System.getSecurityManager() != null) {
|
||||
return AccessController.doPrivileged(
|
||||
(PrivilegedAction<Boolean>) () -> {
|
||||
return iw.imageUpdate(img, info, x, y, w, h);
|
||||
}, acc);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean newInfo(Image img, int info,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
// Note tail recursion because items are added LIFO.
|
||||
boolean ret = next.newInfo(img, info, x, y, w, h);
|
||||
ImageObserver myiw = myref.get();
|
||||
if (myiw == null) {
|
||||
// My referent is null so we must prune in a second pass.
|
||||
ret = true;
|
||||
} else if (update(myiw, myref.acc, img, info, x, y, w, h) == false) {
|
||||
// My referent has lost interest so clear it and ask
|
||||
// for a pruning pass to remove it later.
|
||||
myref.clear();
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addWatcher(ImageObserver iw) {
|
||||
if (iw != null && !isWatcher(iw)) {
|
||||
watcherList = new WeakLink(iw, watcherList);
|
||||
}
|
||||
watcherList = watcherList.removeWatcher(null);
|
||||
}
|
||||
|
||||
public synchronized boolean isWatcher(ImageObserver iw) {
|
||||
return watcherList.isWatcher(iw);
|
||||
}
|
||||
|
||||
public void removeWatcher(ImageObserver iw) {
|
||||
synchronized (this) {
|
||||
watcherList = watcherList.removeWatcher(iw);
|
||||
}
|
||||
if (watcherList == endlink) {
|
||||
notifyWatcherListEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWatcherListEmpty() {
|
||||
synchronized (this) {
|
||||
watcherList = watcherList.removeWatcher(null);
|
||||
}
|
||||
return (watcherList == endlink);
|
||||
}
|
||||
|
||||
public void newInfo(Image img, int info, int x, int y, int w, int h) {
|
||||
if (watcherList.newInfo(img, info, x, y, w, h)) {
|
||||
// Some Link returned true so we now need to prune dead links.
|
||||
removeWatcher(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void notifyWatcherListEmpty();
|
||||
}
|
||||
278
jdkSrc/jdk8/sun/awt/image/ImagingLib.java
Normal file
278
jdkSrc/jdk8/sun/awt/image/ImagingLib.java
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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 sun.awt.image;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ByteLookupTable;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.Kernel;
|
||||
import java.awt.image.LookupOp;
|
||||
import java.awt.image.LookupTable;
|
||||
import java.awt.image.RasterOp;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* This class provides a hook to access platform-specific
|
||||
* imaging code.
|
||||
*
|
||||
* If the implementing class cannot handle the op, tile format or
|
||||
* image format, the method will return null;
|
||||
* If there is an error when processing the
|
||||
* data, the implementing class may either return null
|
||||
* (in which case our java code will be executed) or may throw
|
||||
* an exception.
|
||||
*/
|
||||
public class ImagingLib {
|
||||
|
||||
static boolean useLib = true;
|
||||
static boolean verbose = false;
|
||||
|
||||
private static final int NUM_NATIVE_OPS = 3;
|
||||
private static final int LOOKUP_OP = 0;
|
||||
private static final int AFFINE_OP = 1;
|
||||
private static final int CONVOLVE_OP = 2;
|
||||
|
||||
private static Class[] nativeOpClass = new Class[NUM_NATIVE_OPS];
|
||||
|
||||
/**
|
||||
* Returned value indicates whether the library initailization was
|
||||
* succeded.
|
||||
*
|
||||
* There could be number of reasons to failure:
|
||||
* - failed to load library.
|
||||
* - failed to get all required entry points.
|
||||
*/
|
||||
private static native boolean init();
|
||||
|
||||
static public native int transformBI(BufferedImage src, BufferedImage dst,
|
||||
double[] matrix, int interpType);
|
||||
static public native int transformRaster(Raster src, Raster dst,
|
||||
double[] matrix,
|
||||
int interpType);
|
||||
static public native int convolveBI(BufferedImage src, BufferedImage dst,
|
||||
Kernel kernel, int edgeHint);
|
||||
static public native int convolveRaster(Raster src, Raster dst,
|
||||
Kernel kernel, int edgeHint);
|
||||
static public native int lookupByteBI(BufferedImage src, BufferedImage dst,
|
||||
byte[][] table);
|
||||
static public native int lookupByteRaster(Raster src, Raster dst,
|
||||
byte[][] table);
|
||||
|
||||
static {
|
||||
|
||||
PrivilegedAction<Boolean> doMlibInitialization =
|
||||
new PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
String arch = System.getProperty("os.arch");
|
||||
|
||||
if (arch == null || !arch.startsWith("sparc")) {
|
||||
try {
|
||||
System.loadLibrary("mlib_image");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
boolean success = init();
|
||||
return Boolean.valueOf(success);
|
||||
}
|
||||
};
|
||||
|
||||
useLib = AccessController.doPrivileged(doMlibInitialization);
|
||||
|
||||
//
|
||||
// Cache the class references of the operations we know about
|
||||
// at the time this class is initially loaded.
|
||||
//
|
||||
try {
|
||||
nativeOpClass[LOOKUP_OP] =
|
||||
Class.forName("java.awt.image.LookupOp");
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Could not find class: "+e);
|
||||
}
|
||||
try {
|
||||
nativeOpClass[AFFINE_OP] =
|
||||
Class.forName("java.awt.image.AffineTransformOp");
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Could not find class: "+e);
|
||||
}
|
||||
try {
|
||||
nativeOpClass[CONVOLVE_OP] =
|
||||
Class.forName("java.awt.image.ConvolveOp");
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Could not find class: "+e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int getNativeOpIndex(Class opClass) {
|
||||
//
|
||||
// Search for this class in cached list of
|
||||
// classes supplying native acceleration
|
||||
//
|
||||
int opIndex = -1;
|
||||
for (int i=0; i<NUM_NATIVE_OPS; i++) {
|
||||
if (opClass == nativeOpClass[i]) {
|
||||
opIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return opIndex;
|
||||
}
|
||||
|
||||
|
||||
public static WritableRaster filter(RasterOp op, Raster src,
|
||||
WritableRaster dst) {
|
||||
if (useLib == false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create the destination tile
|
||||
if (dst == null) {
|
||||
dst = op.createCompatibleDestRaster(src);
|
||||
}
|
||||
|
||||
|
||||
WritableRaster retRaster = null;
|
||||
switch (getNativeOpIndex(op.getClass())) {
|
||||
|
||||
case LOOKUP_OP:
|
||||
// REMIND: Fix this!
|
||||
LookupTable table = ((LookupOp)op).getTable();
|
||||
if (table.getOffset() != 0) {
|
||||
// Right now the native code doesn't support offsets
|
||||
return null;
|
||||
}
|
||||
if (table instanceof ByteLookupTable) {
|
||||
ByteLookupTable bt = (ByteLookupTable) table;
|
||||
if (lookupByteRaster(src, dst, bt.getTable()) > 0) {
|
||||
retRaster = dst;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AFFINE_OP:
|
||||
AffineTransformOp bOp = (AffineTransformOp) op;
|
||||
double[] matrix = new double[6];
|
||||
bOp.getTransform().getMatrix(matrix);
|
||||
if (transformRaster(src, dst, matrix,
|
||||
bOp.getInterpolationType()) > 0) {
|
||||
retRaster = dst;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONVOLVE_OP:
|
||||
ConvolveOp cOp = (ConvolveOp) op;
|
||||
if (convolveRaster(src, dst,
|
||||
cOp.getKernel(), cOp.getEdgeCondition()) > 0) {
|
||||
retRaster = dst;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (retRaster != null) {
|
||||
SunWritableRaster.markDirty(retRaster);
|
||||
}
|
||||
|
||||
return retRaster;
|
||||
}
|
||||
|
||||
|
||||
public static BufferedImage filter(BufferedImageOp op, BufferedImage src,
|
||||
BufferedImage dst)
|
||||
{
|
||||
if (verbose) {
|
||||
System.out.println("in filter and op is "+op
|
||||
+ "bufimage is "+src+" and "+dst);
|
||||
}
|
||||
|
||||
if (useLib == false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create the destination image
|
||||
if (dst == null) {
|
||||
dst = op.createCompatibleDestImage(src, null);
|
||||
}
|
||||
|
||||
BufferedImage retBI = null;
|
||||
switch (getNativeOpIndex(op.getClass())) {
|
||||
|
||||
case LOOKUP_OP:
|
||||
// REMIND: Fix this!
|
||||
LookupTable table = ((LookupOp)op).getTable();
|
||||
if (table.getOffset() != 0) {
|
||||
// Right now the native code doesn't support offsets
|
||||
return null;
|
||||
}
|
||||
if (table instanceof ByteLookupTable) {
|
||||
ByteLookupTable bt = (ByteLookupTable) table;
|
||||
if (lookupByteBI(src, dst, bt.getTable()) > 0) {
|
||||
retBI = dst;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AFFINE_OP:
|
||||
AffineTransformOp bOp = (AffineTransformOp) op;
|
||||
double[] matrix = new double[6];
|
||||
AffineTransform xform = bOp.getTransform();
|
||||
bOp.getTransform().getMatrix(matrix);
|
||||
|
||||
if (transformBI(src, dst, matrix,
|
||||
bOp.getInterpolationType())>0) {
|
||||
retBI = dst;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONVOLVE_OP:
|
||||
ConvolveOp cOp = (ConvolveOp) op;
|
||||
if (convolveBI(src, dst, cOp.getKernel(),
|
||||
cOp.getEdgeCondition()) > 0) {
|
||||
retBI = dst;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (retBI != null) {
|
||||
SunWritableRaster.markDirty(retBI);
|
||||
}
|
||||
|
||||
return retBI;
|
||||
}
|
||||
}
|
||||
352
jdkSrc/jdk8/sun/awt/image/InputStreamImageSource.java
Normal file
352
jdkSrc/jdk8/sun/awt/image/InputStreamImageSource.java
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
|
||||
import java.awt.image.*;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public abstract class InputStreamImageSource implements ImageProducer,
|
||||
ImageFetchable
|
||||
{
|
||||
ImageConsumerQueue consumers;
|
||||
|
||||
ImageDecoder decoder;
|
||||
ImageDecoder decoders;
|
||||
|
||||
boolean awaitingFetch = false;
|
||||
|
||||
abstract boolean checkSecurity(Object context, boolean quiet);
|
||||
|
||||
int countConsumers(ImageConsumerQueue cq) {
|
||||
int i = 0;
|
||||
while (cq != null) {
|
||||
i++;
|
||||
cq = cq.next;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
synchronized int countConsumers() {
|
||||
ImageDecoder id = decoders;
|
||||
int i = countConsumers(consumers);
|
||||
while (id != null) {
|
||||
i += countConsumers(id.queue);
|
||||
id = id.next;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public void addConsumer(ImageConsumer ic) {
|
||||
addConsumer(ic, false);
|
||||
}
|
||||
|
||||
synchronized void printQueue(ImageConsumerQueue cq, String prefix) {
|
||||
while (cq != null) {
|
||||
System.out.println(prefix+cq);
|
||||
cq = cq.next;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void printQueues(String title) {
|
||||
System.out.println(title+"[ -----------");
|
||||
printQueue(consumers, " ");
|
||||
for (ImageDecoder id = decoders; id != null; id = id.next) {
|
||||
System.out.println(" "+id);
|
||||
printQueue(id.queue, " ");
|
||||
}
|
||||
System.out.println("----------- ]"+title);
|
||||
}
|
||||
|
||||
synchronized void addConsumer(ImageConsumer ic, boolean produce) {
|
||||
checkSecurity(null, false);
|
||||
for (ImageDecoder id = decoders; id != null; id = id.next) {
|
||||
if (id.isConsumer(ic)) {
|
||||
// This consumer is already being fed.
|
||||
return;
|
||||
}
|
||||
}
|
||||
ImageConsumerQueue cq = consumers;
|
||||
while (cq != null && cq.consumer != ic) {
|
||||
cq = cq.next;
|
||||
}
|
||||
if (cq == null) {
|
||||
cq = new ImageConsumerQueue(this, ic);
|
||||
cq.next = consumers;
|
||||
consumers = cq;
|
||||
} else {
|
||||
if (!cq.secure) {
|
||||
Object context = null;
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
context = security.getSecurityContext();
|
||||
}
|
||||
if (cq.securityContext == null) {
|
||||
cq.securityContext = context;
|
||||
} else if (!cq.securityContext.equals(context)) {
|
||||
// If there are two different security contexts that both
|
||||
// have a handle on the same ImageConsumer, then there has
|
||||
// been a security breach and whether or not they trade
|
||||
// image data is small fish compared to what they could be
|
||||
// trading. Throw a Security exception anyway...
|
||||
errorConsumer(cq, false);
|
||||
throw new SecurityException("Applets are trading image data!");
|
||||
}
|
||||
}
|
||||
cq.interested = true;
|
||||
}
|
||||
if (produce && decoder == null) {
|
||||
startProduction();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isConsumer(ImageConsumer ic) {
|
||||
for (ImageDecoder id = decoders; id != null; id = id.next) {
|
||||
if (id.isConsumer(ic)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return ImageConsumerQueue.isConsumer(consumers, ic);
|
||||
}
|
||||
|
||||
private void errorAllConsumers(ImageConsumerQueue cq, boolean needReload) {
|
||||
while (cq != null) {
|
||||
if (cq.interested) {
|
||||
errorConsumer(cq, needReload);
|
||||
}
|
||||
cq = cq.next;
|
||||
}
|
||||
}
|
||||
|
||||
private void errorConsumer(ImageConsumerQueue cq, boolean needReload) {
|
||||
cq.consumer.imageComplete(ImageConsumer.IMAGEERROR);
|
||||
if ( needReload && cq.consumer instanceof ImageRepresentation) {
|
||||
((ImageRepresentation)cq.consumer).image.flush();
|
||||
}
|
||||
removeConsumer(cq.consumer);
|
||||
}
|
||||
|
||||
public synchronized void removeConsumer(ImageConsumer ic) {
|
||||
for (ImageDecoder id = decoders; id != null; id = id.next) {
|
||||
id.removeConsumer(ic);
|
||||
}
|
||||
consumers = ImageConsumerQueue.removeConsumer(consumers, ic, false);
|
||||
}
|
||||
|
||||
public void startProduction(ImageConsumer ic) {
|
||||
addConsumer(ic, true);
|
||||
}
|
||||
|
||||
private synchronized void startProduction() {
|
||||
if (!awaitingFetch) {
|
||||
if (ImageFetcher.add(this)) {
|
||||
awaitingFetch = true;
|
||||
} else {
|
||||
ImageConsumerQueue cq = consumers;
|
||||
consumers = null;
|
||||
errorAllConsumers(cq, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void stopProduction() {
|
||||
if (awaitingFetch) {
|
||||
ImageFetcher.remove(this);
|
||||
awaitingFetch = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void requestTopDownLeftRightResend(ImageConsumer ic) {
|
||||
}
|
||||
|
||||
protected abstract ImageDecoder getDecoder();
|
||||
|
||||
protected ImageDecoder decoderForType(InputStream is,
|
||||
String content_type) {
|
||||
// Don't believe the content type - file extensions can
|
||||
// lie.
|
||||
/*
|
||||
if (content_type.equals("image/gif")) {
|
||||
return new GifImageDecoder(this, is);
|
||||
} else if (content_type.equals("image/jpeg")) {
|
||||
return new JPEGImageDecoder(this, is);
|
||||
} else if (content_type.equals("image/x-xbitmap")) {
|
||||
return new XbmImageDecoder(this, is);
|
||||
}
|
||||
else if (content_type == URL.content_jpeg) {
|
||||
return new JpegImageDecoder(this, is);
|
||||
} else if (content_type == URL.content_xbitmap) {
|
||||
return new XbmImageDecoder(this, is);
|
||||
} else if (content_type == URL.content_xpixmap) {
|
||||
return new Xpm2ImageDecoder(this, is);
|
||||
}
|
||||
*/
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ImageDecoder getDecoder(InputStream is) {
|
||||
if (!is.markSupported())
|
||||
is = new BufferedInputStream(is);
|
||||
try {
|
||||
/* changed to support png
|
||||
is.mark(6);
|
||||
*/
|
||||
is.mark(8);
|
||||
int c1 = is.read();
|
||||
int c2 = is.read();
|
||||
int c3 = is.read();
|
||||
int c4 = is.read();
|
||||
int c5 = is.read();
|
||||
int c6 = is.read();
|
||||
// added to support png
|
||||
int c7 = is.read();
|
||||
int c8 = is.read();
|
||||
// end of adding
|
||||
is.reset();
|
||||
is.mark(-1);
|
||||
|
||||
if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
|
||||
return new GifImageDecoder(this, is);
|
||||
} else if (c1 == '\377' && c2 == '\330' && c3 == '\377') {
|
||||
return new JPEGImageDecoder(this, is);
|
||||
} else if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') {
|
||||
return new XbmImageDecoder(this, is);
|
||||
// } else if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' &&
|
||||
// c5 == 'M' && c6 == '2') {
|
||||
// return new Xpm2ImageDecoder(this, is);
|
||||
// added to support png
|
||||
} else if (c1 == 137 && c2 == 80 && c3 == 78 &&
|
||||
c4 == 71 && c5 == 13 && c6 == 10 &&
|
||||
c7 == 26 && c8 == 10) {
|
||||
return new PNGImageDecoder(this, is);
|
||||
}
|
||||
// end of adding
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void doFetch() {
|
||||
synchronized (this) {
|
||||
if (consumers == null) {
|
||||
awaitingFetch = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
ImageDecoder imgd = getDecoder();
|
||||
if (imgd == null) {
|
||||
badDecoder();
|
||||
} else {
|
||||
setDecoder(imgd);
|
||||
try {
|
||||
imgd.produceImage();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
// the finally clause will send an error.
|
||||
} catch (ImageFormatException e) {
|
||||
e.printStackTrace();
|
||||
// the finally clause will send an error.
|
||||
} finally {
|
||||
removeDecoder(imgd);
|
||||
if ( Thread.currentThread().isInterrupted() || !Thread.currentThread().isAlive()) {
|
||||
errorAllConsumers(imgd.queue, true);
|
||||
} else {
|
||||
errorAllConsumers(imgd.queue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void badDecoder() {
|
||||
ImageConsumerQueue cq;
|
||||
synchronized (this) {
|
||||
cq = consumers;
|
||||
consumers = null;
|
||||
awaitingFetch = false;
|
||||
}
|
||||
errorAllConsumers(cq, false);
|
||||
}
|
||||
|
||||
private void setDecoder(ImageDecoder mydecoder) {
|
||||
ImageConsumerQueue cq;
|
||||
synchronized (this) {
|
||||
mydecoder.next = decoders;
|
||||
decoders = mydecoder;
|
||||
decoder = mydecoder;
|
||||
cq = consumers;
|
||||
mydecoder.queue = cq;
|
||||
consumers = null;
|
||||
awaitingFetch = false;
|
||||
}
|
||||
while (cq != null) {
|
||||
if (cq.interested) {
|
||||
// Now that there is a decoder, security may have changed
|
||||
// so reverify it here, just in case.
|
||||
if (!checkSecurity(cq.securityContext, true)) {
|
||||
errorConsumer(cq, false);
|
||||
}
|
||||
}
|
||||
cq = cq.next;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeDecoder(ImageDecoder mydecoder) {
|
||||
doneDecoding(mydecoder);
|
||||
ImageDecoder idprev = null;
|
||||
for (ImageDecoder id = decoders; id != null; id = id.next) {
|
||||
if (id == mydecoder) {
|
||||
if (idprev == null) {
|
||||
decoders = id.next;
|
||||
} else {
|
||||
idprev.next = id.next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
idprev = id;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void doneDecoding(ImageDecoder mydecoder) {
|
||||
if (decoder == mydecoder) {
|
||||
decoder = null;
|
||||
if (consumers != null) {
|
||||
startProduction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void latchConsumers(ImageDecoder id) {
|
||||
doneDecoding(id);
|
||||
}
|
||||
|
||||
synchronized void flush() {
|
||||
decoder = null;
|
||||
}
|
||||
}
|
||||
748
jdkSrc/jdk8/sun/awt/image/IntegerComponentRaster.java
Normal file
748
jdkSrc/jdk8/sun/awt/image/IntegerComponentRaster.java
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of one or more 32-bit
|
||||
* data elements stored in close proximity to each other in a integer array.
|
||||
* The bit precision per data element is that
|
||||
* of the data type (that is, the bit precision for this raster is 32).
|
||||
* There is only one pixel stride and one scanline stride for all
|
||||
* bands. For a given pixel, all samples fit in N data elements and these
|
||||
* N data elements hold samples for only one pixel. This type of Raster
|
||||
* can be used with a PackedColorModel.
|
||||
* <p>
|
||||
* For example, if there is only one data element per pixel, a
|
||||
* SinglePixelPackedSampleModel can be used to represent multiple
|
||||
* bands with a PackedColorModel (including a DirectColorModel) for
|
||||
* color interpretation.
|
||||
*
|
||||
*/
|
||||
public class IntegerComponentRaster extends SunWritableRaster {
|
||||
|
||||
static final int TYPE_CUSTOM = 0;
|
||||
static final int TYPE_BYTE_SAMPLES = 1;
|
||||
static final int TYPE_USHORT_SAMPLES = 2;
|
||||
static final int TYPE_INT_SAMPLES = 3;
|
||||
static final int TYPE_BYTE_BANDED_SAMPLES = 4;
|
||||
static final int TYPE_USHORT_BANDED_SAMPLES = 5;
|
||||
static final int TYPE_INT_BANDED_SAMPLES = 6;
|
||||
static final int TYPE_BYTE_PACKED_SAMPLES = 7;
|
||||
static final int TYPE_USHORT_PACKED_SAMPLES = 8;
|
||||
static final int TYPE_INT_PACKED_SAMPLES = 9;
|
||||
static final int TYPE_INT_8BIT_SAMPLES = 10;
|
||||
static final int TYPE_BYTE_BINARY_SAMPLES = 11;
|
||||
|
||||
/** private band offset for use by native code */
|
||||
protected int bandOffset;
|
||||
|
||||
/** Data offsets for each band of image data. */
|
||||
protected int[] dataOffsets;
|
||||
|
||||
/** Scanline stride of the image data contained in this Raster. */
|
||||
protected int scanlineStride;
|
||||
|
||||
/** Pixel stride of the image data contained in this Raster. */
|
||||
protected int pixelStride;
|
||||
|
||||
/** The image data array. */
|
||||
protected int[] data;
|
||||
|
||||
/** The number of data elements required to store a pixel. */
|
||||
protected int numDataElems;
|
||||
|
||||
int type;
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
static private native void initIDs();
|
||||
static {
|
||||
/* ensure that the necessary native libraries are loaded */
|
||||
NativeLibLoader.loadLibraries();
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a IntegerComponentRaster with the given SampleModel.
|
||||
* The Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A DataBuffer large enough to describe the
|
||||
* Raster is automatically created. SampleModel must be of type
|
||||
* SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specified the origin.
|
||||
*/
|
||||
public IntegerComponentRaster(SampleModel sampleModel,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a IntegerComponentRaster with the given SampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same sizes the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferInt compatible with SampleModel.
|
||||
* SampleModel must be of type SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferInt that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public IntegerComponentRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
dataBuffer,
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a IntegerComponentRaster with the given SampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferInt and
|
||||
* SampleModel must be of type SinglePixelPackedSampleModel.
|
||||
* When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coodinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferInt that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public IntegerComponentRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
IntegerComponentRaster parent){
|
||||
super(sampleModel,dataBuffer,aRegion,origin,parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
if (!(dataBuffer instanceof DataBufferInt)) {
|
||||
throw new RasterFormatException("IntegerComponentRasters must have" +
|
||||
"integer DataBuffers");
|
||||
}
|
||||
DataBufferInt dbi = (DataBufferInt)dataBuffer;
|
||||
if (dbi.getNumBanks() != 1) {
|
||||
throw new
|
||||
RasterFormatException("DataBuffer for IntegerComponentRasters"+
|
||||
" must only have 1 bank.");
|
||||
}
|
||||
this.data = stealData(dbi, 0);
|
||||
|
||||
if (sampleModel instanceof SinglePixelPackedSampleModel) {
|
||||
SinglePixelPackedSampleModel sppsm =
|
||||
(SinglePixelPackedSampleModel)sampleModel;
|
||||
int[] boffsets = sppsm.getBitOffsets();
|
||||
boolean notByteBoundary = false;
|
||||
for (int i=1; i < boffsets.length; i++) {
|
||||
if ((boffsets[i]%8) != 0) {
|
||||
notByteBoundary = true;
|
||||
}
|
||||
}
|
||||
this.type = (notByteBoundary
|
||||
? IntegerComponentRaster.TYPE_INT_PACKED_SAMPLES
|
||||
: IntegerComponentRaster.TYPE_INT_8BIT_SAMPLES);
|
||||
|
||||
this.scanlineStride = sppsm.getScanlineStride();
|
||||
this.pixelStride = 1;
|
||||
this.dataOffsets = new int[1];
|
||||
this.dataOffsets[0] = dbi.getOffset();
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
dataOffsets[0] += xOffset+yOffset*scanlineStride;
|
||||
this.numDataElems = sppsm.getNumDataElements();
|
||||
} else {
|
||||
throw new RasterFormatException("IntegerComponentRasters must have"+
|
||||
" SinglePixelPackedSampleModel");
|
||||
}
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data offset
|
||||
* is the index into the band's data array, of the first sample of the
|
||||
* band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[]) dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data offset for the specified band. The data offset
|
||||
* is the index into the data array in which the first sample
|
||||
* of the first scanline is stored.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements between
|
||||
* a given sample and the sample in the same column of the next row.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel stride -- the number of data array elements between two
|
||||
* samples for the same band on the same scanline.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return pixelStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the data array.
|
||||
*/
|
||||
public int[] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int outData[];
|
||||
if (obj == null) {
|
||||
outData = new int[numDataElements];
|
||||
} else {
|
||||
outData = (int[])obj;
|
||||
}
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
for (int band = 0; band < numDataElements; band++) {
|
||||
outData[band] = data[dataOffsets[band] + off];
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
<pre>
|
||||
* int[] bandData = (int[])raster.getDataElements(x, y, w, h, null);
|
||||
* int numDataElements = raster.getNumDataElements();
|
||||
* int[] pixel = new int[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int outData[];
|
||||
if (obj instanceof int[]) {
|
||||
outData = (int[])obj;
|
||||
} else {
|
||||
outData = new int[numDataElements*w*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores the data elements for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int inData[] = (int[])obj;
|
||||
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
data[dataOffsets[i] + off] = inData[i];
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* The transferType of the inputRaster must match this raster.
|
||||
* An ArrayIndexOutOfBoundsException will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
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.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write inRaster (minX, minY) to (dstX, dstY)
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
int tdata[] = null;
|
||||
|
||||
if (inRaster instanceof IntegerComponentRaster &&
|
||||
(pixelStride == 1) && (numDataElements == 1)) {
|
||||
IntegerComponentRaster ict = (IntegerComponentRaster) inRaster;
|
||||
if (ict.getNumDataElements() != 1) {
|
||||
throw new ArrayIndexOutOfBoundsException("Number of bands"+
|
||||
" does not match");
|
||||
}
|
||||
|
||||
// Extract the raster parameters
|
||||
tdata = ict.getDataStorage();
|
||||
int tss = ict.getScanlineStride();
|
||||
int toff = ict.getDataOffset(0);
|
||||
|
||||
int srcOffset = toff;
|
||||
|
||||
int dstOffset = dataOffsets[0]+(dstY-minY)*scanlineStride+
|
||||
(dstX-minX);
|
||||
|
||||
|
||||
// Fastest case. We can copy scanlines
|
||||
if (ict.getPixelStride() == pixelStride) {
|
||||
width *= pixelStride;
|
||||
|
||||
// Loop through all of the scanlines and copy the data
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
System.arraycopy(tdata, srcOffset, data, dstOffset, width);
|
||||
srcOffset += tss;
|
||||
dstOffset += scanlineStride;
|
||||
}
|
||||
markDirty();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Object odata = null;
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
odata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, odata);
|
||||
setDataElements(dstX, dstY+startY,
|
||||
width, 1, odata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int inData[] = (int[])obj;
|
||||
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* DataBuffer as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.minX + this.width)) {
|
||||
throw new RasterFormatException("(x + width) is outside raster");
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.minY + this.height)) {
|
||||
throw new RasterFormatException("(y + height) is outside raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new IntegerComponentRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0,y0,width,height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. Note that the subraster will reference the same
|
||||
* DataBuffer as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subRaster.
|
||||
* @param y0 Translated Y origin of the subRaster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
return createWritableChild(x, y, width, height, x0, y0, bandList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a raster with the same band layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w,h);
|
||||
|
||||
return new IntegerComponentRaster(sm, new Point(0,0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a raster with the same data layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the raster is a subraster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
*
|
||||
* The method verifies whether scanline stride and pixel stride do not
|
||||
* cause an integer overflow during calculation of a position of the pixel
|
||||
* in data buffer. It also verifies whether the data buffer has enough data
|
||||
* to correspond the raster layout attributes.
|
||||
*
|
||||
* @throws RasterFormatException if an integer overflow is detected,
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
protected final void verify() {
|
||||
/* Need to re-verify the dimensions since a sample model may be
|
||||
* specified to the constructor
|
||||
*/
|
||||
if (width <= 0 || height <= 0 ||
|
||||
height > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
|
||||
if (dataOffsets[0] < 0) {
|
||||
throw new RasterFormatException("Data offset ("+dataOffsets[0]+
|
||||
") must be >= 0");
|
||||
}
|
||||
|
||||
if ((long)minX - sampleModelTranslateX < 0 ||
|
||||
(long)minY - sampleModelTranslateY < 0) {
|
||||
|
||||
throw new RasterFormatException("Incorrect origin/translate: (" +
|
||||
minX + ", " + minY + ") / (" +
|
||||
sampleModelTranslateX + ", " + sampleModelTranslateY + ")");
|
||||
}
|
||||
|
||||
// we can be sure that width and height are greater than 0
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
|
||||
if (height > 1 || minY - sampleModelTranslateY > 0) {
|
||||
// buffer should contain at least one scanline
|
||||
if (scanlineStride > data.length) {
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
}
|
||||
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
|
||||
if (pixelStride < 0 ||
|
||||
pixelStride > (Integer.MAX_VALUE / width) ||
|
||||
pixelStride > data.length)
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect pixel stride: "
|
||||
+ pixelStride);
|
||||
}
|
||||
int lastPixelOffset = (width - 1) * pixelStride;
|
||||
|
||||
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect raster attributes");
|
||||
}
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
int index;
|
||||
int maxIndex = 0;
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
}
|
||||
|
||||
index = lastPixelOffset + dataOffsets[i];
|
||||
|
||||
if (index > maxIndex) {
|
||||
maxIndex = index;
|
||||
}
|
||||
}
|
||||
if (data.length <= maxIndex) {
|
||||
throw new RasterFormatException("Data array too small (should be > "
|
||||
+ maxIndex + " )");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("IntegerComponentRaster: width = "+width
|
||||
+" height = " + height
|
||||
+" #Bands = " + numBands
|
||||
+" #DataElements "+numDataElements
|
||||
+" xOff = "+sampleModelTranslateX
|
||||
+" yOff = "+sampleModelTranslateY
|
||||
+" dataOffset[0] "+dataOffsets[0]);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * For debugging... prints a region of a one-band IntegerComponentRaster
|
||||
// */
|
||||
// public void print(int x, int y, int w, int h) {
|
||||
// // REMIND: Only works for 1 band!
|
||||
// System.out.println(this);
|
||||
// int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride;
|
||||
// int off;
|
||||
// for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) {
|
||||
// off = offset;
|
||||
// System.out.print("Line "+(sampleModelTranslateY+y+yoff)+": ");
|
||||
// for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) {
|
||||
// System.out.print(Integer.toHexString(data[off])+" ");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
570
jdkSrc/jdk8/sun/awt/image/IntegerInterleavedRaster.java
Normal file
570
jdkSrc/jdk8/sun/awt/image/IntegerInterleavedRaster.java
Normal file
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of one or more 32-bit
|
||||
* data elements stored in close proximity to each other in a integer array.
|
||||
* The bit precision per data element is that
|
||||
* of the data type (that is, the bit precision for this raster is 32).
|
||||
* There is only one pixel stride and one scanline stride for all
|
||||
* bands. For a given pixel, all samples fit in N data elements and these
|
||||
* N data elements hold samples for only one pixel. This type of Raster
|
||||
* can be used with a PackedColorModel.
|
||||
* <p>
|
||||
* For example, if there is only one data element per pixel, a
|
||||
* SinglePixelPackedSampleModel can be used to represent multiple
|
||||
* bands with a PackedColorModel (including a DirectColorModel) for
|
||||
* color interpretation.
|
||||
*
|
||||
*/
|
||||
public class IntegerInterleavedRaster extends IntegerComponentRaster {
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
/**
|
||||
* Constructs a IntegerInterleavedRaster with the given SampleModel.
|
||||
* The Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A DataBuffer large enough to describe the
|
||||
* Raster is automatically created. SampleModel must be of type
|
||||
* SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specified the origin.
|
||||
*/
|
||||
public IntegerInterleavedRaster(SampleModel sampleModel,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a IntegerInterleavedRaster with the given SampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same sizes the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferInt compatible with SampleModel.
|
||||
* SampleModel must be of type SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferInt that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public IntegerInterleavedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
dataBuffer,
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a IntegerInterleavedRaster with the given SampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferInt and
|
||||
* SampleModel must be of type SinglePixelPackedSampleModel.
|
||||
* When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coodinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferInt that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public IntegerInterleavedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
IntegerInterleavedRaster parent){
|
||||
super(sampleModel,dataBuffer,aRegion,origin,parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
if (!(dataBuffer instanceof DataBufferInt)) {
|
||||
throw new RasterFormatException("IntegerInterleavedRasters must have" +
|
||||
"integer DataBuffers");
|
||||
}
|
||||
DataBufferInt dbi = (DataBufferInt)dataBuffer;
|
||||
this.data = stealData(dbi, 0);
|
||||
|
||||
if (sampleModel instanceof SinglePixelPackedSampleModel) {
|
||||
SinglePixelPackedSampleModel sppsm =
|
||||
(SinglePixelPackedSampleModel)sampleModel;
|
||||
this.scanlineStride = sppsm.getScanlineStride();
|
||||
this.pixelStride = 1;
|
||||
this.dataOffsets = new int[1];
|
||||
this.dataOffsets[0] = dbi.getOffset();
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
dataOffsets[0] += xOffset+yOffset*scanlineStride;
|
||||
this.numDataElems = sppsm.getNumDataElements();
|
||||
} else {
|
||||
throw new RasterFormatException("IntegerInterleavedRasters must have"+
|
||||
" SinglePixelPackedSampleModel");
|
||||
}
|
||||
verify();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data offset
|
||||
* is the index into the band's data array, of the first sample of the
|
||||
* band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[]) dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data offset for the specified band. The data offset
|
||||
* is the index into the data array in which the first sample
|
||||
* of the first scanline is stored.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements between
|
||||
* a given sample and the sample in the same column of the next row.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel stride -- the number of data array elements between two
|
||||
* samples for the same band on the same scanline.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return pixelStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the data array.
|
||||
*/
|
||||
public int[] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int outData[];
|
||||
if (obj == null) {
|
||||
outData = new int[1];
|
||||
} else {
|
||||
outData = (int[])obj;
|
||||
}
|
||||
int off = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0];
|
||||
outData[0] = data[off];
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
<pre>
|
||||
* int[] bandData = (int[])raster.getDataElements(x, y, w, h, null);
|
||||
* int numDataElements = raster.getNumDataElements();
|
||||
* int[] pixel = new int[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int outData[];
|
||||
if (obj instanceof int[]) {
|
||||
outData = (int[])obj;
|
||||
} else {
|
||||
outData = new int[w*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0];
|
||||
int off = 0;
|
||||
|
||||
for (int ystart = 0; ystart < h; ystart++) {
|
||||
System.arraycopy(data, yoff, outData, off, w);
|
||||
off += w;
|
||||
yoff += scanlineStride;
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores the data elements for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int inData[] = (int[])obj;
|
||||
|
||||
int off = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0];
|
||||
|
||||
data[off] = inData[0];
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* The transferType of the inputRaster must match this raster.
|
||||
* An ArrayIndexOutOfBoundsException will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
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.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write inRaster (minX, minY) to (dstX, dstY)
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
int tdata[] = null;
|
||||
|
||||
if (inRaster instanceof IntegerInterleavedRaster) {
|
||||
IntegerInterleavedRaster ict = (IntegerInterleavedRaster) inRaster;
|
||||
|
||||
// Extract the raster parameters
|
||||
tdata = ict.getDataStorage();
|
||||
int tss = ict.getScanlineStride();
|
||||
int toff = ict.getDataOffset(0);
|
||||
|
||||
int srcOffset = toff;
|
||||
int dstOffset = dataOffsets[0]+(dstY-minY)*scanlineStride+
|
||||
(dstX-minX);
|
||||
|
||||
|
||||
// Fastest case. We can copy scanlines
|
||||
// Loop through all of the scanlines and copy the data
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
System.arraycopy(tdata, srcOffset, data, dstOffset, width);
|
||||
srcOffset += tss;
|
||||
dstOffset += scanlineStride;
|
||||
}
|
||||
markDirty();
|
||||
return;
|
||||
}
|
||||
|
||||
Object odata = null;
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
// Grab one scanline at a time
|
||||
odata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, odata);
|
||||
setDataElements(dstX, dstY+startY, width, 1, odata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int inData[] = (int[])obj;
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[0];
|
||||
int off = 0;
|
||||
|
||||
for (int ystart = 0; ystart < h; ystart++) {
|
||||
System.arraycopy(inData, off, data, yoff, w);
|
||||
off += w;
|
||||
yoff += scanlineStride;
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* DataBuffer as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.minX + this.width)) {
|
||||
throw new RasterFormatException("(x + width) is outside raster");
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.minY + this.height)) {
|
||||
throw new RasterFormatException("(y + height) is outside raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new IntegerInterleavedRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0,y0,width,height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. Note that the subraster will reference the same
|
||||
* DataBuffer as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subRaster.
|
||||
* @param y0 Translated Y origin of the subRaster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
return createWritableChild(x, y, width, height, x0, y0, bandList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a raster with the same band layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w,h);
|
||||
|
||||
return new IntegerInterleavedRaster(sm, new Point(0,0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a raster with the same data layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the raster is a subraster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("IntegerInterleavedRaster: width = "+width
|
||||
+" height = " + height
|
||||
+" #Bands = " + numBands
|
||||
+" xOff = "+sampleModelTranslateX
|
||||
+" yOff = "+sampleModelTranslateY
|
||||
+" dataOffset[0] "+dataOffsets[0]);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * For debugging... prints a region of a one-band IntegerInterleavedRaster
|
||||
// */
|
||||
// public void print(int x, int y, int w, int h) {
|
||||
// // REMIND: Only works for 1 band!
|
||||
// System.out.println(this);
|
||||
// int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride;
|
||||
// int off;
|
||||
// for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) {
|
||||
// off = offset;
|
||||
// System.out.print("Line "+(sampleModelTranslateY+y+yoff)+": ");
|
||||
// for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) {
|
||||
// System.out.print(Integer.toHexString(data[off])+" ");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
160
jdkSrc/jdk8/sun/awt/image/JPEGImageDecoder.java
Normal file
160
jdkSrc/jdk8/sun/awt/image/JPEGImageDecoder.java
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2012, 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.
|
||||
*/
|
||||
/*-
|
||||
* Reads JPEG images from an InputStream and reports the
|
||||
* image data to an InputStreamImageSource object.
|
||||
*
|
||||
* The native implementation of the JPEG image decoder was adapted from
|
||||
* release 6 of the free JPEG software from the Independent JPEG Group.
|
||||
*/
|
||||
package sun.awt.image;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Hashtable;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* JPEG Image converter
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
public class JPEGImageDecoder extends ImageDecoder {
|
||||
private static ColorModel RGBcolormodel;
|
||||
private static ColorModel ARGBcolormodel;
|
||||
private static ColorModel Graycolormodel;
|
||||
|
||||
private static final Class InputStreamClass = InputStream.class;
|
||||
private static native void initIDs(Class InputStreamClass);
|
||||
|
||||
private ColorModel colormodel;
|
||||
|
||||
static {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("jpeg");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
initIDs(InputStreamClass);
|
||||
RGBcolormodel = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
ARGBcolormodel = ColorModel.getRGBdefault();
|
||||
byte g[] = new byte[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
g[i] = (byte) i;
|
||||
}
|
||||
Graycolormodel = new IndexColorModel(8, 256, g, g, g);
|
||||
}
|
||||
|
||||
private native void readImage(InputStream is, byte buf[])
|
||||
throws ImageFormatException, IOException;
|
||||
|
||||
Hashtable props = new Hashtable();
|
||||
|
||||
public JPEGImageDecoder(InputStreamImageSource src, InputStream is) {
|
||||
super(src, is);
|
||||
}
|
||||
|
||||
/**
|
||||
* An error has occurred. Throw an exception.
|
||||
*/
|
||||
private static void error(String s1) throws ImageFormatException {
|
||||
throw new ImageFormatException(s1);
|
||||
}
|
||||
|
||||
public boolean sendHeaderInfo(int width, int height,
|
||||
boolean gray, boolean hasalpha,
|
||||
boolean multipass)
|
||||
{
|
||||
setDimensions(width, height);
|
||||
|
||||
setProperties(props);
|
||||
if (gray) {
|
||||
colormodel = Graycolormodel;
|
||||
} else {
|
||||
if (hasalpha) {
|
||||
colormodel = ARGBcolormodel;
|
||||
} else {
|
||||
colormodel = RGBcolormodel;
|
||||
}
|
||||
}
|
||||
|
||||
setColorModel(colormodel);
|
||||
|
||||
int flags = hintflags;
|
||||
if (!multipass) {
|
||||
flags |= ImageConsumer.SINGLEPASS;
|
||||
}
|
||||
setHints(hintflags);
|
||||
headerComplete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean sendPixels(int pixels[], int y) {
|
||||
int count = setPixels(0, y, pixels.length, 1, colormodel,
|
||||
pixels, 0, pixels.length);
|
||||
if (count <= 0) {
|
||||
aborted = true;
|
||||
}
|
||||
return !aborted;
|
||||
}
|
||||
|
||||
public boolean sendPixels(byte pixels[], int y) {
|
||||
int count = setPixels(0, y, pixels.length, 1, colormodel,
|
||||
pixels, 0, pixels.length);
|
||||
if (count <= 0) {
|
||||
aborted = true;
|
||||
}
|
||||
return !aborted;
|
||||
}
|
||||
|
||||
/**
|
||||
* produce an image from the stream.
|
||||
*/
|
||||
public void produceImage() throws IOException, ImageFormatException {
|
||||
try {
|
||||
readImage(input, new byte[1024]);
|
||||
if (!aborted) {
|
||||
imageComplete(ImageConsumer.STATICIMAGEDONE, true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!aborted) {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The ImageConsumer hints flag for a JPEG image.
|
||||
*/
|
||||
private static final int hintflags =
|
||||
ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEFRAME;
|
||||
}
|
||||
181
jdkSrc/jdk8/sun/awt/image/MultiResolutionCachedImage.java
Normal file
181
jdkSrc/jdk8/sun/awt/image/MultiResolutionCachedImage.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Image;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
|
||||
private final int baseImageWidth;
|
||||
private final int baseImageHeight;
|
||||
private final Dimension2D[] sizes;
|
||||
private final BiFunction<Integer, Integer, Image> mapper;
|
||||
private int availableInfo;
|
||||
|
||||
public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
|
||||
BiFunction<Integer, Integer, Image> mapper) {
|
||||
this(baseImageWidth, baseImageHeight, new Dimension[]{new Dimension(
|
||||
baseImageWidth, baseImageHeight)
|
||||
}, mapper);
|
||||
}
|
||||
|
||||
public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
|
||||
Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) {
|
||||
this.baseImageWidth = baseImageWidth;
|
||||
this.baseImageHeight = baseImageHeight;
|
||||
this.sizes = (sizes == null) ? null : Arrays.copyOf(sizes, sizes.length);
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
ImageCache cache = ImageCache.getInstance();
|
||||
ImageCacheKey key = new ImageCacheKey(this, width, height);
|
||||
Image resolutionVariant = cache.getImage(key);
|
||||
if (resolutionVariant == null) {
|
||||
resolutionVariant = mapper.apply(width, height);
|
||||
cache.setImage(key, resolutionVariant);
|
||||
}
|
||||
preload(resolutionVariant, availableInfo);
|
||||
return resolutionVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getResolutionVariants() {
|
||||
return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size
|
||||
-> getResolutionVariant((int) size.getWidth(),
|
||||
(int) size.getHeight())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public MultiResolutionCachedImage map(Function<Image, Image> mapper) {
|
||||
return new MultiResolutionCachedImage(baseImageWidth, baseImageHeight,
|
||||
sizes, (width, height) ->
|
||||
mapper.apply(getResolutionVariant(width, height)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth(ImageObserver observer) {
|
||||
updateInfo(observer, ImageObserver.WIDTH);
|
||||
return super.getWidth(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(ImageObserver observer) {
|
||||
updateInfo(observer, ImageObserver.HEIGHT);
|
||||
return super.getHeight(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name, ImageObserver observer) {
|
||||
updateInfo(observer, ImageObserver.PROPERTIES);
|
||||
return super.getProperty(name, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Image getBaseImage() {
|
||||
return getResolutionVariant(baseImageWidth, baseImageHeight);
|
||||
}
|
||||
|
||||
private void updateInfo(ImageObserver observer, int info) {
|
||||
availableInfo |= (observer == null) ? ImageObserver.ALLBITS : info;
|
||||
}
|
||||
|
||||
private static int getInfo(Image image) {
|
||||
if (image instanceof ToolkitImage) {
|
||||
return ((ToolkitImage) image).getImageRep().check(
|
||||
(img, infoflags, x, y, w, h) -> false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void preload(Image image, int availableInfo) {
|
||||
if (availableInfo != 0 && image instanceof ToolkitImage) {
|
||||
((ToolkitImage) image).preload(new ImageObserver() {
|
||||
int flags = availableInfo;
|
||||
|
||||
@Override
|
||||
public boolean imageUpdate(Image img, int infoflags,
|
||||
int x, int y, int width, int height) {
|
||||
flags &= ~infoflags;
|
||||
return (flags != 0) && ((infoflags
|
||||
& (ImageObserver.ERROR | ImageObserver.ABORT)) == 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImageCacheKey implements ImageCache.PixelsKey {
|
||||
|
||||
private final int pixelCount;
|
||||
private final int hash;
|
||||
|
||||
private final int w;
|
||||
private final int h;
|
||||
private final Image baseImage;
|
||||
|
||||
ImageCacheKey(final Image baseImage,
|
||||
final int w, final int h) {
|
||||
this.baseImage = baseImage;
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.pixelCount = w * h;
|
||||
hash = hash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPixelCount() {
|
||||
return pixelCount;
|
||||
}
|
||||
|
||||
private int hash() {
|
||||
int hash = baseImage.hashCode();
|
||||
hash = 31 * hash + w;
|
||||
hash = 31 * hash + h;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ImageCacheKey) {
|
||||
ImageCacheKey key = (ImageCacheKey) obj;
|
||||
return baseImage == key.baseImage && w == key.w && h == key.h;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
83
jdkSrc/jdk8/sun/awt/image/MultiResolutionImage.java
Normal file
83
jdkSrc/jdk8/sun/awt/image/MultiResolutionImage.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 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 sun.awt.image;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This interface is designed to provide a set of images at various resolutions.
|
||||
*
|
||||
* The <code>MultiResolutionImage</code> interface should be implemented by any
|
||||
* class whose instances are intended to provide image resolution variants
|
||||
* according to the given image width and height.
|
||||
*
|
||||
* For example,
|
||||
* <pre>
|
||||
* {@code
|
||||
* public class ScaledImage extends BufferedImage
|
||||
* implements MultiResolutionImage {
|
||||
*
|
||||
* @Override
|
||||
* public Image getResolutionVariant(int width, int height) {
|
||||
* return ((width <= getWidth() && height <= getHeight()))
|
||||
* ? this : highResolutionImage;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public List<Image> getResolutionVariants() {
|
||||
* return Arrays.asList(this, highResolutionImage);
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* It is recommended to cache image variants for performance reasons.
|
||||
*
|
||||
* <b>WARNING</b>: This class is an implementation detail. This API may change
|
||||
* between update release, and it may even be removed or be moved in some other
|
||||
* package(s)/class(es).
|
||||
*/
|
||||
public interface MultiResolutionImage {
|
||||
|
||||
/**
|
||||
* Provides an image with necessary resolution which best fits to the given
|
||||
* image width and height.
|
||||
*
|
||||
* @param width the desired image resolution width.
|
||||
* @param height the desired image resolution height.
|
||||
* @return image resolution variant.
|
||||
*
|
||||
* @since JDK1.8
|
||||
*/
|
||||
public Image getResolutionVariant(int width, int height);
|
||||
|
||||
/**
|
||||
* Gets list of all resolution variants including the base image
|
||||
*
|
||||
* @return list of resolution variants.
|
||||
* @since JDK1.8
|
||||
*/
|
||||
public List<Image> getResolutionVariants();
|
||||
}
|
||||
117
jdkSrc/jdk8/sun/awt/image/MultiResolutionToolkitImage.java
Normal file
117
jdkSrc/jdk8/sun/awt/image/MultiResolutionToolkitImage.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 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 sun.awt.image;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import sun.misc.SoftCache;
|
||||
|
||||
public class MultiResolutionToolkitImage extends ToolkitImage implements MultiResolutionImage {
|
||||
|
||||
Image resolutionVariant;
|
||||
|
||||
public MultiResolutionToolkitImage(Image lowResolutionImage, Image resolutionVariant) {
|
||||
super(lowResolutionImage.getSource());
|
||||
this.resolutionVariant = resolutionVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
return ((width <= getWidth() && height <= getHeight()))
|
||||
? this : resolutionVariant;
|
||||
}
|
||||
|
||||
public Image getResolutionVariant() {
|
||||
return resolutionVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getResolutionVariants() {
|
||||
return Arrays.<Image>asList(this, resolutionVariant);
|
||||
}
|
||||
|
||||
private static final int BITS_INFO = ImageObserver.SOMEBITS
|
||||
| ImageObserver.FRAMEBITS | ImageObserver.ALLBITS;
|
||||
|
||||
private static class ObserverCache {
|
||||
|
||||
static final SoftCache INSTANCE = new SoftCache();
|
||||
}
|
||||
|
||||
public static ImageObserver getResolutionVariantObserver(
|
||||
final Image image, final ImageObserver observer,
|
||||
final int imgWidth, final int imgHeight,
|
||||
final int rvWidth, final int rvHeight) {
|
||||
return getResolutionVariantObserver(image, observer,
|
||||
imgWidth, imgHeight, rvWidth, rvHeight, false);
|
||||
}
|
||||
|
||||
public static ImageObserver getResolutionVariantObserver(
|
||||
final Image image, final ImageObserver observer,
|
||||
final int imgWidth, final int imgHeight,
|
||||
final int rvWidth, final int rvHeight, boolean concatenateInfo) {
|
||||
|
||||
if (observer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized (ObserverCache.INSTANCE) {
|
||||
ImageObserver o = (ImageObserver) ObserverCache.INSTANCE.get(observer);
|
||||
|
||||
if (o == null) {
|
||||
|
||||
o = (Image resolutionVariant, int flags,
|
||||
int x, int y, int width, int height) -> {
|
||||
|
||||
if ((flags & (ImageObserver.WIDTH | BITS_INFO)) != 0) {
|
||||
width = (width + 1) / 2;
|
||||
}
|
||||
|
||||
if ((flags & (ImageObserver.HEIGHT | BITS_INFO)) != 0) {
|
||||
height = (height + 1) / 2;
|
||||
}
|
||||
|
||||
if ((flags & BITS_INFO) != 0) {
|
||||
x /= 2;
|
||||
y /= 2;
|
||||
}
|
||||
|
||||
if(concatenateInfo){
|
||||
flags &= ((ToolkitImage) image).
|
||||
getImageRep().check(null);
|
||||
}
|
||||
|
||||
return observer.imageUpdate(
|
||||
image, flags, x, y, width, height);
|
||||
};
|
||||
|
||||
ObserverCache.INSTANCE.put(observer, o);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
jdkSrc/jdk8/sun/awt/image/NativeLibLoader.java
Normal file
64
jdkSrc/jdk8/sun/awt/image/NativeLibLoader.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, 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 sun.awt.image;
|
||||
|
||||
class NativeLibLoader {
|
||||
|
||||
/**
|
||||
* This is copied from java.awt.Toolkit since we need the library
|
||||
* loaded in sun.awt.image also:
|
||||
*
|
||||
* WARNING: This is a temporary workaround for a problem in the
|
||||
* way the AWT loads native libraries. A number of classes in this
|
||||
* package (sun.awt.image) have a native method, initIDs(),
|
||||
* which initializes
|
||||
* the JNI field and method ids used in the native portion of
|
||||
* their implementation.
|
||||
*
|
||||
* Since the use and storage of these ids is done by the
|
||||
* implementation libraries, the implementation of these method is
|
||||
* provided by the particular AWT implementations
|
||||
* (i.e. "Toolkit"s/Peer), such as Motif, Win32 or Tiny. The
|
||||
* problem is that this means that the native libraries must be
|
||||
* loaded by the java.* classes, which do not necessarily know the
|
||||
* names of the libraries to load. A better way of doing this
|
||||
* would be to provide a separate library which defines java.awt.*
|
||||
* initIDs, and exports the relevant symbols out to the
|
||||
* implementation libraries.
|
||||
*
|
||||
* For now, we know it's done by the implementation, and we assume
|
||||
* that the name of the library is "awt". -br.
|
||||
*/
|
||||
static void loadLibraries() {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("awt");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
115
jdkSrc/jdk8/sun/awt/image/OffScreenImage.java
Normal file
115
jdkSrc/jdk8/sun/awt/image/OffScreenImage.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Color;
|
||||
import java.awt.SystemColor;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* This is a special variant of BufferedImage that keeps a reference to
|
||||
* a Component. The Component's foreground and background colors and
|
||||
* default font are used as the defaults for this image.
|
||||
*/
|
||||
public class OffScreenImage extends BufferedImage {
|
||||
|
||||
protected Component c;
|
||||
private OffScreenImageSource osis;
|
||||
private Font defaultFont;
|
||||
|
||||
/**
|
||||
* Constructs an OffScreenImage given a color model and tile,
|
||||
* for offscreen rendering to be used with a given component.
|
||||
* The component is used to obtain the foreground color, background
|
||||
* color and font.
|
||||
*/
|
||||
public OffScreenImage(Component c, ColorModel cm, WritableRaster raster,
|
||||
boolean isRasterPremultiplied)
|
||||
{
|
||||
super(cm, raster, isRasterPremultiplied, null);
|
||||
this.c = c;
|
||||
initSurface(raster.getWidth(), raster.getHeight());
|
||||
}
|
||||
|
||||
public Graphics getGraphics() {
|
||||
return createGraphics();
|
||||
}
|
||||
|
||||
public Graphics2D createGraphics() {
|
||||
if (c == null) {
|
||||
GraphicsEnvironment env =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
return env.createGraphics(this);
|
||||
}
|
||||
|
||||
Color bg = c.getBackground();
|
||||
if (bg == null) {
|
||||
bg = SystemColor.window;
|
||||
}
|
||||
|
||||
Color fg = c.getForeground();
|
||||
if (fg == null) {
|
||||
fg = SystemColor.windowText;
|
||||
}
|
||||
|
||||
Font font = c.getFont();
|
||||
if (font == null) {
|
||||
if (defaultFont == null) {
|
||||
defaultFont = new Font("Dialog", Font.PLAIN, 12);
|
||||
}
|
||||
font = defaultFont;
|
||||
}
|
||||
|
||||
return new SunGraphics2D(SurfaceData.getPrimarySurfaceData(this),
|
||||
fg, bg, font);
|
||||
}
|
||||
|
||||
private void initSurface(int width, int height) {
|
||||
Graphics2D g2 = createGraphics();
|
||||
try {
|
||||
g2.clearRect(0, 0, width, height);
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public ImageProducer getSource() {
|
||||
if (osis == null) {
|
||||
osis = new OffScreenImageSource(this);
|
||||
}
|
||||
return osis;
|
||||
}
|
||||
}
|
||||
196
jdkSrc/jdk8/sun/awt/image/OffScreenImageSource.java
Normal file
196
jdkSrc/jdk8/sun/awt/image/OffScreenImageSource.java
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2012, 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 sun.awt.image;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.awt.image.ImageConsumer;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
public class OffScreenImageSource implements ImageProducer {
|
||||
BufferedImage image;
|
||||
int width;
|
||||
int height;
|
||||
Hashtable properties;
|
||||
|
||||
public OffScreenImageSource(BufferedImage image,
|
||||
Hashtable properties) {
|
||||
this.image = image;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new Hashtable();
|
||||
}
|
||||
width = image.getWidth();
|
||||
height = image.getHeight();
|
||||
}
|
||||
|
||||
public OffScreenImageSource(BufferedImage image) {
|
||||
this(image, null);
|
||||
}
|
||||
|
||||
// We can only have one consumer since we immediately return the data...
|
||||
private ImageConsumer theConsumer;
|
||||
|
||||
public synchronized void addConsumer(ImageConsumer ic) {
|
||||
theConsumer = ic;
|
||||
produce();
|
||||
}
|
||||
|
||||
public synchronized boolean isConsumer(ImageConsumer ic) {
|
||||
return (ic == theConsumer);
|
||||
}
|
||||
|
||||
public synchronized void removeConsumer(ImageConsumer ic) {
|
||||
if (theConsumer == ic) {
|
||||
theConsumer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void startProduction(ImageConsumer ic) {
|
||||
addConsumer(ic);
|
||||
}
|
||||
|
||||
public void requestTopDownLeftRightResend(ImageConsumer ic) {
|
||||
}
|
||||
|
||||
private void sendPixels() {
|
||||
ColorModel cm = image.getColorModel();
|
||||
WritableRaster raster = image.getRaster();
|
||||
int numDataElements = raster.getNumDataElements();
|
||||
int dataType = raster.getDataBuffer().getDataType();
|
||||
int[] scanline = new int[width*numDataElements];
|
||||
boolean needToCvt = true;
|
||||
|
||||
if (cm instanceof IndexColorModel) {
|
||||
byte[] pixels = new byte[width];
|
||||
theConsumer.setColorModel(cm);
|
||||
|
||||
if (raster instanceof ByteComponentRaster) {
|
||||
needToCvt = false;
|
||||
for (int y=0; y < height; y++) {
|
||||
raster.getDataElements(0, y, width, 1, pixels);
|
||||
theConsumer.setPixels(0, y, width, 1, cm, pixels, 0,
|
||||
width);
|
||||
}
|
||||
}
|
||||
else if (raster instanceof BytePackedRaster) {
|
||||
needToCvt = false;
|
||||
// Binary image. Need to unpack it
|
||||
for (int y=0; y < height; y++) {
|
||||
raster.getPixels(0, y, width, 1, scanline);
|
||||
for (int x=0; x < width; x++) {
|
||||
pixels[x] = (byte) scanline[x];
|
||||
}
|
||||
theConsumer.setPixels(0, y, width, 1, cm, pixels, 0,
|
||||
width);
|
||||
}
|
||||
}
|
||||
else if (dataType == DataBuffer.TYPE_SHORT ||
|
||||
dataType == DataBuffer.TYPE_INT)
|
||||
{
|
||||
// Probably a short or int "GRAY" image
|
||||
needToCvt = false;
|
||||
for (int y=0; y < height; y++) {
|
||||
raster.getPixels(0, y, width, 1, scanline);
|
||||
theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
|
||||
width);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cm instanceof DirectColorModel) {
|
||||
theConsumer.setColorModel(cm);
|
||||
needToCvt = false;
|
||||
switch (dataType) {
|
||||
case DataBuffer.TYPE_INT:
|
||||
for (int y=0; y < height; y++) {
|
||||
raster.getDataElements(0, y, width, 1, scanline);
|
||||
theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
|
||||
width);
|
||||
}
|
||||
break;
|
||||
case DataBuffer.TYPE_BYTE:
|
||||
byte[] bscanline = new byte[width];
|
||||
for (int y=0; y < height; y++) {
|
||||
raster.getDataElements(0, y, width, 1, bscanline);
|
||||
for (int x=0; x < width; x++) {
|
||||
scanline[x] = bscanline[x]&0xff;
|
||||
}
|
||||
theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
|
||||
width);
|
||||
}
|
||||
break;
|
||||
case DataBuffer.TYPE_USHORT:
|
||||
short[] sscanline = new short[width];
|
||||
for (int y=0; y < height; y++) {
|
||||
raster.getDataElements(0, y, width, 1, sscanline);
|
||||
for (int x=0; x < width; x++) {
|
||||
scanline[x] = sscanline[x]&0xffff;
|
||||
}
|
||||
theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
|
||||
width);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
needToCvt = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToCvt) {
|
||||
// REMIND: Need to add other types of CMs here
|
||||
ColorModel newcm = ColorModel.getRGBdefault();
|
||||
theConsumer.setColorModel(newcm);
|
||||
|
||||
for (int y=0; y < height; y++) {
|
||||
for (int x=0; x < width; x++) {
|
||||
scanline[x] = image.getRGB(x, y);
|
||||
}
|
||||
theConsumer.setPixels(0, y, width, 1, newcm, scanline, 0,
|
||||
width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void produce() {
|
||||
try {
|
||||
theConsumer.setDimensions(image.getWidth(), image.getHeight());
|
||||
theConsumer.setProperties(properties);
|
||||
sendPixels();
|
||||
theConsumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
|
||||
theConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
|
||||
} catch (NullPointerException e) {
|
||||
if (theConsumer != null) {
|
||||
theConsumer.imageComplete(ImageConsumer.IMAGEERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
840
jdkSrc/jdk8/sun/awt/image/PNGImageDecoder.java
Normal file
840
jdkSrc/jdk8/sun/awt/image/PNGImageDecoder.java
Normal file
@@ -0,0 +1,840 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, 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 sun.awt.image;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.Color;
|
||||
|
||||
/** PNG - Portable Network Graphics - image file reader.
|
||||
See <a href=http://www.ietf.org/rfc/rfc2083.txt>RFC2083</a> for details. */
|
||||
|
||||
/* this is changed
|
||||
public class PNGImageDecoder extends FilterInputStream implements Runnable
|
||||
{ */
|
||||
|
||||
public class PNGImageDecoder extends ImageDecoder
|
||||
{
|
||||
private static final int GRAY=0;
|
||||
private static final int PALETTE=1;
|
||||
private static final int COLOR=2;
|
||||
private static final int ALPHA=4;
|
||||
|
||||
private static final int bKGDChunk = 0x624B4744;
|
||||
private static final int cHRMChunk = 0x6348524D;
|
||||
private static final int gAMAChunk = 0x67414D41;
|
||||
private static final int hISTChunk = 0x68495354;
|
||||
private static final int IDATChunk = 0x49444154;
|
||||
private static final int IENDChunk = 0x49454E44;
|
||||
private static final int IHDRChunk = 0x49484452;
|
||||
private static final int PLTEChunk = 0x504C5445;
|
||||
private static final int pHYsChunk = 0x70485973;
|
||||
private static final int sBITChunk = 0x73424954;
|
||||
private static final int tEXtChunk = 0x74455874;
|
||||
private static final int tIMEChunk = 0x74494D45;
|
||||
private static final int tRNSChunk = 0x74524E53;
|
||||
private static final int zTXtChunk = 0x7A545874;
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private int bitDepth;
|
||||
private int colorType;
|
||||
private int compressionMethod;
|
||||
private int filterMethod;
|
||||
private int interlaceMethod;
|
||||
private int gamma = 100000;
|
||||
private java.util.Hashtable properties;
|
||||
/* this is not needed
|
||||
ImageConsumer target;
|
||||
*/
|
||||
private ColorModel cm;
|
||||
private byte[] red_map, green_map, blue_map, alpha_map;
|
||||
private int transparentPixel = -1;
|
||||
private byte[] transparentPixel_16 = null; // we need 6 bytes to store 16bpp value
|
||||
private static ColorModel greyModels[] = new ColorModel[4];
|
||||
/* this is not needed
|
||||
PNGImageDecoder next;
|
||||
*/
|
||||
|
||||
private void property(String key,Object value) {
|
||||
if(value==null) return;
|
||||
if(properties==null) properties=new java.util.Hashtable();
|
||||
properties.put(key,value);
|
||||
}
|
||||
private void property(String key,float value) {
|
||||
property(key,new Float(value));
|
||||
}
|
||||
private final void pngassert(boolean b) throws IOException {
|
||||
if(!b) {
|
||||
PNGException e = new PNGException("Broken file");
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
protected boolean handleChunk(int key, byte[] buf, int st, int len)
|
||||
throws IOException {
|
||||
switch(key) {
|
||||
case bKGDChunk:
|
||||
Color c = null;
|
||||
switch(colorType) {
|
||||
case COLOR:
|
||||
case COLOR|ALPHA:
|
||||
pngassert(len==6);
|
||||
c = new Color(buf[st]&0xff,buf[st+2]&0xff,buf[st+4]&0xff);
|
||||
break;
|
||||
case COLOR|PALETTE:
|
||||
case COLOR|PALETTE|ALPHA:
|
||||
pngassert(len==1);
|
||||
int ix = buf[st]&0xFF;
|
||||
pngassert(red_map!=null && ix<red_map.length);
|
||||
c = new Color(red_map[ix]&0xff,green_map[ix]&0xff,blue_map[ix]&0xff);
|
||||
break;
|
||||
case GRAY:
|
||||
case GRAY|ALPHA:
|
||||
pngassert(len==2);
|
||||
int t = buf[st]&0xFF;
|
||||
c = new Color(t,t,t);
|
||||
break;
|
||||
}
|
||||
if(c!=null) property("background",c);
|
||||
break;
|
||||
case cHRMChunk:
|
||||
property("chromaticities",
|
||||
new Chromaticities(
|
||||
getInt(st),
|
||||
getInt(st+4),
|
||||
getInt(st+8),
|
||||
getInt(st+12),
|
||||
getInt(st+16),
|
||||
getInt(st+20),
|
||||
getInt(st+24),
|
||||
getInt(st+28)));
|
||||
break;
|
||||
case gAMAChunk:
|
||||
if(len!=4) throw new PNGException("bogus gAMA");
|
||||
gamma = getInt(st);
|
||||
if(gamma!=100000) property("gamma",gamma/100000.0f);
|
||||
break;
|
||||
case hISTChunk: break;
|
||||
case IDATChunk: return false;
|
||||
case IENDChunk: break;
|
||||
case IHDRChunk:
|
||||
if(len!=13
|
||||
||(width = getInt(st))==0
|
||||
||(height = getInt(st+4))==0
|
||||
) throw new PNGException("bogus IHDR");
|
||||
bitDepth = getByte(st+8);
|
||||
colorType = getByte(st+9);
|
||||
compressionMethod = getByte(st+10);
|
||||
filterMethod = getByte(st+11);
|
||||
interlaceMethod = getByte(st+12);
|
||||
/* this is not needed
|
||||
if(target!=null) target.setDimensions(width,height);
|
||||
*/
|
||||
break;
|
||||
case PLTEChunk:
|
||||
{ int tsize = len/3;
|
||||
red_map = new byte[tsize];
|
||||
green_map = new byte[tsize];
|
||||
blue_map = new byte[tsize];
|
||||
for(int i=0,j=st; i<tsize; i++, j+=3) {
|
||||
red_map[i] = buf[j];
|
||||
green_map[i] = buf[j+1];
|
||||
blue_map[i] = buf[j+2];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case pHYsChunk: break;
|
||||
case sBITChunk: break;
|
||||
case tEXtChunk:
|
||||
int klen = 0;
|
||||
while(klen<len && buf[st+klen]!=0) klen++;
|
||||
if(klen<len) {
|
||||
String tkey = new String(buf,st,klen);
|
||||
String tvalue = new String(buf,st+klen+1,len-klen-1);
|
||||
property(tkey,tvalue);
|
||||
}
|
||||
break;
|
||||
case tIMEChunk:
|
||||
property("modtime",new GregorianCalendar(
|
||||
getShort(st+0),
|
||||
getByte(st+2)-1,
|
||||
getByte(st+3),
|
||||
getByte(st+4),
|
||||
getByte(st+5),
|
||||
getByte(st+6)).getTime());
|
||||
break;
|
||||
case tRNSChunk:
|
||||
switch(colorType) {
|
||||
case PALETTE|COLOR:
|
||||
case PALETTE|COLOR|ALPHA:
|
||||
int alen = len;
|
||||
if(red_map!=null) alen = red_map.length;
|
||||
alpha_map = new byte[alen];
|
||||
System.arraycopy(buf,st,alpha_map,0,len<alen ? len : alen);
|
||||
while (--alen>=len) alpha_map[alen] = (byte)0xFF;
|
||||
break;
|
||||
case COLOR: // doesn't deal with 16 bit colors properly
|
||||
case COLOR|ALPHA: // doesn't deal with 16 bit colors properly
|
||||
pngassert(len==6);
|
||||
if (bitDepth == 16) {
|
||||
transparentPixel_16 = new byte[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
transparentPixel_16[i] = (byte)getByte(st + i);
|
||||
}
|
||||
} else {
|
||||
transparentPixel =
|
||||
((getShort(st + 0)&0xFF)<<16)
|
||||
| ((getShort(st + 2)&0xFF)<< 8)
|
||||
| ((getShort(st + 4)&0xFF) );
|
||||
}
|
||||
break;
|
||||
case GRAY: // doesn't deal with 16 bit colors properly
|
||||
case GRAY|ALPHA: // doesn't deal with 16 bit colors properly
|
||||
pngassert(len==2);
|
||||
/* REMIND: Discarding the LSB for 16 bit depth here
|
||||
* means that the all pixels which match the MSB
|
||||
* will be treated as transparent.
|
||||
*/
|
||||
int t = getShort(st);
|
||||
t = 0xFF & ((bitDepth == 16) ? (t >> 8) : t);
|
||||
transparentPixel = (t<<16) | (t<< 8) | t;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case zTXtChunk: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public class PNGException extends IOException {
|
||||
PNGException(String s) { super(s); }
|
||||
}
|
||||
/* this is changed
|
||||
public void run() {
|
||||
*/
|
||||
public void produceImage() throws IOException, ImageFormatException {
|
||||
/* this is not needed
|
||||
ImageConsumer t = target;
|
||||
if(t!=null) try {
|
||||
*/
|
||||
try {
|
||||
for(int i=0; i<signature.length; i++)
|
||||
if((signature[i]&0xFF)!=underlyingInputStream.read())
|
||||
throw new PNGException("Chunk signature mismatch");
|
||||
|
||||
InputStream is = new BufferedInputStream(new InflaterInputStream(inputStream,new Inflater()));
|
||||
|
||||
getData();
|
||||
|
||||
byte[] bPixels = null;
|
||||
int[] wPixels = null;
|
||||
int pixSize = width;
|
||||
int rowStride;
|
||||
int logDepth = 0;
|
||||
switch(bitDepth) {
|
||||
case 1: logDepth = 0; break;
|
||||
case 2: logDepth = 1; break;
|
||||
case 4: logDepth = 2; break;
|
||||
case 8: logDepth = 3; break;
|
||||
case 16: logDepth = 4; break;
|
||||
default: throw new PNGException("invalid depth");
|
||||
}
|
||||
if(interlaceMethod!=0) {pixSize *= height;rowStride=width;}
|
||||
else rowStride = 0;
|
||||
int combinedType = colorType|(bitDepth<<3);
|
||||
int bitMask = (1<<(bitDepth>=8?8:bitDepth))-1;
|
||||
//Figure out the color model
|
||||
switch(colorType) {
|
||||
case COLOR|PALETTE:
|
||||
case COLOR|PALETTE|ALPHA:
|
||||
if(red_map==null) throw new PNGException("palette expected");
|
||||
if(alpha_map==null)
|
||||
cm = new IndexColorModel(bitDepth,red_map.length,
|
||||
red_map,green_map,blue_map);
|
||||
else
|
||||
cm = new IndexColorModel(bitDepth,red_map.length,
|
||||
red_map,green_map,blue_map,alpha_map);
|
||||
bPixels = new byte[pixSize];
|
||||
break;
|
||||
case GRAY:
|
||||
{ int llog = logDepth>=4 ? 3 : logDepth;
|
||||
if((cm=greyModels[llog]) == null) {
|
||||
int size = 1<<(1<<llog);
|
||||
|
||||
byte ramp[] = new byte[size];
|
||||
for(int i = 0; i<size; i++) ramp[i] = (byte)(255*i/(size-1));
|
||||
|
||||
if (transparentPixel == -1) {
|
||||
cm = new IndexColorModel(bitDepth,ramp.length,ramp,ramp,ramp);
|
||||
} else {
|
||||
cm = new IndexColorModel(bitDepth,ramp.length,ramp,ramp,ramp,
|
||||
(transparentPixel & 0xFF));
|
||||
}
|
||||
greyModels[llog] = cm;
|
||||
}
|
||||
}
|
||||
bPixels = new byte[pixSize];
|
||||
break;
|
||||
case COLOR:
|
||||
case COLOR|ALPHA:
|
||||
case GRAY|ALPHA:
|
||||
cm = ColorModel.getRGBdefault();
|
||||
wPixels = new int[pixSize];
|
||||
break;
|
||||
default:
|
||||
throw new PNGException("invalid color type");
|
||||
}
|
||||
/* this is going to be set in the pixel store
|
||||
t.setColorModel(cm);
|
||||
t.setHints(interlaceMethod !=0
|
||||
? ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES
|
||||
: ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME);
|
||||
*/
|
||||
// code added to make it work with ImageDecoder architecture
|
||||
setDimensions(width, height);
|
||||
setColorModel(cm);
|
||||
int flags = (interlaceMethod !=0
|
||||
? ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES
|
||||
: ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME);
|
||||
setHints(flags);
|
||||
headerComplete();
|
||||
// end of adding
|
||||
|
||||
int samplesPerPixel = ((colorType&PALETTE)!=0 ? 1
|
||||
: ((colorType&COLOR)!=0 ? 3 : 1)+((colorType&ALPHA)!=0?1:0));
|
||||
int bitsPerPixel = samplesPerPixel*bitDepth;
|
||||
int bytesPerPixel = (bitsPerPixel+7)>>3;
|
||||
int pass, passLimit;
|
||||
if(interlaceMethod==0) { pass = -1; passLimit = 0; }
|
||||
else { pass = 0; passLimit = 7; }
|
||||
// These loops are far from being tuned. They're this way to make them easy to
|
||||
// debug. Tuning comes later.
|
||||
/* code changed. target not needed here
|
||||
while(++pass<=passLimit && (t=target)!=null) {
|
||||
*/
|
||||
while(++pass<=passLimit) {
|
||||
int row = startingRow[pass];
|
||||
int rowInc = rowIncrement[pass];
|
||||
int colInc = colIncrement[pass];
|
||||
int bWidth = blockWidth[pass];
|
||||
int bHeight = blockHeight[pass];
|
||||
int sCol = startingCol[pass];
|
||||
int rowPixelWidth = (width-sCol+(colInc-1))/colInc;
|
||||
int rowByteWidth = ((rowPixelWidth*bitsPerPixel)+7)>>3;
|
||||
if(rowByteWidth==0) continue;
|
||||
int pixelBufferInc = interlaceMethod==0 ? rowInc*width : 0;
|
||||
int rowOffset = rowStride*row;
|
||||
boolean firstRow = true;
|
||||
|
||||
byte[] rowByteBuffer = new byte[rowByteWidth];
|
||||
byte[] prevRowByteBuffer = new byte[rowByteWidth];
|
||||
/* code changed. target not needed here
|
||||
while (row < height && (t=target)!=null) {
|
||||
*/
|
||||
while (row < height) {
|
||||
int rowFilter = is.read();
|
||||
for (int rowFillPos=0;rowFillPos<rowByteWidth; ) {
|
||||
int n = is.read(rowByteBuffer,rowFillPos,rowByteWidth-rowFillPos);
|
||||
if(n<=0) throw new PNGException("missing data");
|
||||
rowFillPos+=n;
|
||||
}
|
||||
filterRow(rowByteBuffer,
|
||||
firstRow ? null : prevRowByteBuffer,
|
||||
rowFilter, rowByteWidth, bytesPerPixel);
|
||||
int col = sCol;
|
||||
int spos=0;
|
||||
int pixel = 0;
|
||||
while (col < width) {
|
||||
if(wPixels !=null) {
|
||||
switch(combinedType) {
|
||||
case COLOR|ALPHA|(8<<3):
|
||||
wPixels[col+rowOffset] =
|
||||
((rowByteBuffer[spos ]&0xFF)<<16)
|
||||
| ((rowByteBuffer[spos+1]&0xFF)<< 8)
|
||||
| ((rowByteBuffer[spos+2]&0xFF) )
|
||||
| ((rowByteBuffer[spos+3]&0xFF)<<24);
|
||||
spos+=4;
|
||||
break;
|
||||
case COLOR|ALPHA|(16<<3):
|
||||
wPixels[col+rowOffset] =
|
||||
((rowByteBuffer[spos ]&0xFF)<<16)
|
||||
| ((rowByteBuffer[spos+2]&0xFF)<< 8)
|
||||
| ((rowByteBuffer[spos+4]&0xFF) )
|
||||
| ((rowByteBuffer[spos+6]&0xFF)<<24);
|
||||
spos+=8;
|
||||
break;
|
||||
case COLOR|(8<<3):
|
||||
pixel =
|
||||
((rowByteBuffer[spos ]&0xFF)<<16)
|
||||
| ((rowByteBuffer[spos+1]&0xFF)<< 8)
|
||||
| ((rowByteBuffer[spos+2]&0xFF) );
|
||||
if (pixel != transparentPixel) {
|
||||
pixel |= 0xff000000;
|
||||
}
|
||||
wPixels[col+rowOffset] = pixel;
|
||||
spos+=3;
|
||||
break;
|
||||
case COLOR|(16<<3):
|
||||
pixel =
|
||||
((rowByteBuffer[spos ]&0xFF)<<16)
|
||||
| ((rowByteBuffer[spos+2]&0xFF)<< 8)
|
||||
| ((rowByteBuffer[spos+4]&0xFF) );
|
||||
|
||||
boolean isTransparent = (transparentPixel_16 != null);
|
||||
for (int i = 0; isTransparent && (i < 6); i++) {
|
||||
isTransparent &=
|
||||
(rowByteBuffer[spos + i] & 0xFF) == (transparentPixel_16[i] & 0xFF);
|
||||
}
|
||||
if (!isTransparent) {
|
||||
pixel |= 0xff000000;
|
||||
}
|
||||
wPixels[col+rowOffset] = pixel;
|
||||
spos+=6;
|
||||
break;
|
||||
case GRAY|ALPHA|(8<<3):
|
||||
{ int tx = rowByteBuffer[spos]&0xFF;
|
||||
wPixels[col+rowOffset] =
|
||||
(tx<<16)|(tx<<8)|tx
|
||||
|((rowByteBuffer[spos+1]&0xFF)<<24); }
|
||||
spos+=2;
|
||||
break;
|
||||
case GRAY|ALPHA|(16<<3):
|
||||
{ int tx = rowByteBuffer[spos]&0xFF;
|
||||
wPixels[col+rowOffset] =
|
||||
(tx<<16)|(tx<<8)|tx
|
||||
|((rowByteBuffer[spos+2]&0xFF)<<24); }
|
||||
spos+=4;
|
||||
break;
|
||||
default: throw new PNGException("illegal type/depth");
|
||||
}
|
||||
} else switch(bitDepth) {
|
||||
case 1:
|
||||
bPixels[col+rowOffset] =
|
||||
(byte)((rowByteBuffer[spos>>3]>>(7-(spos&7)))&1);
|
||||
spos++;
|
||||
break;
|
||||
case 2:
|
||||
bPixels[col+rowOffset] =
|
||||
(byte)((rowByteBuffer[spos>>2]>>((3-(spos&3))*2))&3);
|
||||
spos++;
|
||||
break;
|
||||
case 4:
|
||||
bPixels[col+rowOffset] =
|
||||
(byte)((rowByteBuffer[spos>>1]>>((1-(spos&1))*4))&15);
|
||||
spos++;
|
||||
break;
|
||||
case 8: bPixels[col+rowOffset] = rowByteBuffer[spos++];
|
||||
break;
|
||||
case 16: bPixels[col+rowOffset] = rowByteBuffer[spos]; spos+=2;
|
||||
break;
|
||||
default: throw new PNGException("illegal type/depth");
|
||||
}
|
||||
/*visit (row, col,
|
||||
min (bHeight, height - row),
|
||||
min (bWidth, width - col)); */
|
||||
col += colInc;
|
||||
}
|
||||
if(interlaceMethod==0)
|
||||
if(wPixels!=null) {
|
||||
/* code changed. target not needed here
|
||||
t.setPixels(0,row,width,1,cm,wPixels,0,width);
|
||||
*/
|
||||
// code added to make it work with ImageDecoder arch
|
||||
sendPixels(0,row,width,1,wPixels,0,width);
|
||||
// end of adding
|
||||
}
|
||||
else {
|
||||
/* code changed. target not needed here
|
||||
t.setPixels(0,row,width,1,cm,bPixels,0,width);
|
||||
*/
|
||||
// code added to make it work with ImageDecoder arch
|
||||
sendPixels(0,row,width,1,bPixels,0,width);
|
||||
//end of adding
|
||||
}
|
||||
row += rowInc;
|
||||
rowOffset += rowInc*rowStride;
|
||||
byte[] T = rowByteBuffer;
|
||||
rowByteBuffer = prevRowByteBuffer;
|
||||
prevRowByteBuffer = T;
|
||||
firstRow = false;
|
||||
}
|
||||
if(interlaceMethod!=0)
|
||||
if(wPixels!=null) {
|
||||
/* code changed. target not needed here
|
||||
t.setPixels(0,0,width,height,cm,wPixels,0,width);
|
||||
*/
|
||||
// code added to make it work with ImageDecoder arch
|
||||
sendPixels(0,0,width,height,wPixels,0,width);
|
||||
//end of adding
|
||||
}
|
||||
else {
|
||||
/* code changed. target not needed here
|
||||
t.setPixels(0,0,width,height,cm,bPixels,0,width);
|
||||
*/
|
||||
// code added to make it work with ImageDecoder arch
|
||||
sendPixels(0,0,width,height,bPixels,0,width);
|
||||
//end of adding
|
||||
}
|
||||
}
|
||||
|
||||
/* Here, the function "visit(row,column,height,width)" obtains the
|
||||
next transmitted pixel and paints a rectangle of the specified
|
||||
height and width, whose upper-left corner is at the specified row
|
||||
and column, using the color indicated by the pixel. Note that row
|
||||
and column are measured from 0,0 at the upper left corner. */
|
||||
|
||||
/* code not needed, don't deal with target
|
||||
if((t=target)!=null) {
|
||||
if(properties!=null) t.setProperties(properties);
|
||||
t.imageComplete(ImageConsumer.STATICIMAGEDONE);
|
||||
*/
|
||||
|
||||
imageComplete(ImageConsumer.STATICIMAGEDONE, true);
|
||||
|
||||
/* code not needed }
|
||||
is.close();
|
||||
*/
|
||||
} catch(IOException e) {
|
||||
if(!aborted) {
|
||||
/* code not needed
|
||||
if((t=target)!=null) {
|
||||
PNGEncoder.prChunk(e.toString(),inbuf,pos,limit-pos,true);
|
||||
*/
|
||||
property("error", e);
|
||||
/* code not needed
|
||||
t.setProperties(properties);
|
||||
t.imageComplete(ImageConsumer.IMAGEERROR|ImageConsumer.STATICIMAGEDONE);
|
||||
*/
|
||||
imageComplete(ImageConsumer.IMAGEERROR|ImageConsumer.STATICIMAGEDONE, true);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
try { close(); } catch(Throwable e){}
|
||||
/* code not needed
|
||||
target = null;
|
||||
endTurn();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendPixels(int x, int y, int w, int h, int[] pixels,
|
||||
int offset, int pixlength) {
|
||||
int count = setPixels(x, y, w, h, cm,
|
||||
pixels, offset, pixlength);
|
||||
if (count <= 0) {
|
||||
aborted = true;
|
||||
}
|
||||
return !aborted;
|
||||
}
|
||||
private boolean sendPixels(int x, int y, int w, int h, byte[] pixels,
|
||||
int offset, int pixlength) {
|
||||
int count = setPixels(x, y, w, h, cm,
|
||||
pixels, offset, pixlength);
|
||||
if (count <= 0) {
|
||||
aborted = true;
|
||||
}
|
||||
return !aborted;
|
||||
}
|
||||
|
||||
private void filterRow(byte rowByteBuffer[], byte[] prevRow,
|
||||
int rowFilter, int rowByteWidth, int bytesPerSample)
|
||||
throws IOException {
|
||||
int x = 0;
|
||||
switch (rowFilter) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
for (x = bytesPerSample; x < rowByteWidth; x++)
|
||||
rowByteBuffer[x] += rowByteBuffer[x - bytesPerSample];
|
||||
break;
|
||||
case 2:
|
||||
if (prevRow != null)
|
||||
for ( ; x < rowByteWidth; x++)
|
||||
rowByteBuffer[x] += prevRow[x];
|
||||
break;
|
||||
case 3:
|
||||
if (prevRow != null) {
|
||||
for ( ; x < bytesPerSample; x++)
|
||||
rowByteBuffer[x] += (0xff & prevRow[x])>>1;
|
||||
for ( ; x < rowByteWidth; x++)
|
||||
rowByteBuffer[x] += ((prevRow[x]&0xFF) + (rowByteBuffer[x - bytesPerSample]&0xFF))>>1;
|
||||
} else
|
||||
for (x = bytesPerSample; x < rowByteWidth; x++)
|
||||
rowByteBuffer[x] += (rowByteBuffer[x - bytesPerSample]&0xFF)>>1;
|
||||
break;
|
||||
case 4:
|
||||
if (prevRow != null) {
|
||||
for ( ; x < bytesPerSample; x++)
|
||||
rowByteBuffer[x] += prevRow[x];
|
||||
for ( ; x < rowByteWidth; x++) {
|
||||
int a, b, c, p, pa, pb, pc, rval;
|
||||
a = rowByteBuffer[x - bytesPerSample]&0xFF;
|
||||
b = prevRow[x]&0xFF;
|
||||
c = prevRow[x - bytesPerSample]&0xFF;
|
||||
p = a + b - c;
|
||||
pa = p > a ? p - a : a - p;
|
||||
pb = p > b ? p - b : b - p;
|
||||
pc = p > c ? p - c : c - p;
|
||||
rowByteBuffer[x] += (pa <= pb) && (pa <= pc) ? a : pb <= pc ? b : c;
|
||||
}
|
||||
} else
|
||||
for (x = bytesPerSample; x < rowByteWidth; x++)
|
||||
rowByteBuffer[x] += rowByteBuffer[x - bytesPerSample];
|
||||
break;
|
||||
default:
|
||||
throw new PNGException("Illegal filter");
|
||||
}
|
||||
}
|
||||
private static final byte[] startingRow = { 0, 0, 0, 4, 0, 2, 0, 1 };
|
||||
private static final byte[] startingCol = { 0, 0, 4, 0, 2, 0, 1, 0 };
|
||||
private static final byte[] rowIncrement = { 1, 8, 8, 8, 4, 4, 2, 2 };
|
||||
private static final byte[] colIncrement = { 1, 8, 8, 4, 4, 2, 2, 1 };
|
||||
private static final byte[] blockHeight = { 1, 8, 8, 4, 4, 2, 2, 1 };
|
||||
private static final byte[] blockWidth = { 1, 8, 4, 4, 2, 2, 1, 1 };
|
||||
|
||||
//abstract public class ChunkReader extends FilterInputStream {
|
||||
int pos, limit;
|
||||
int chunkStart;
|
||||
int chunkKey, chunkLength, chunkCRC;
|
||||
boolean seenEOF;
|
||||
|
||||
private static final byte[] signature = { (byte) 137, (byte) 80, (byte) 78,
|
||||
(byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10 };
|
||||
|
||||
PNGFilterInputStream inputStream;
|
||||
InputStream underlyingInputStream;
|
||||
|
||||
/* code changed
|
||||
public PNGImageDecoder(InputStream in, ImageConsumer t) throws IOException {
|
||||
*/
|
||||
public PNGImageDecoder(InputStreamImageSource src, InputStream input) throws IOException {
|
||||
// code added
|
||||
super(src, input);
|
||||
inputStream = new PNGFilterInputStream(this, input);
|
||||
underlyingInputStream = inputStream.underlyingInputStream;
|
||||
// end of adding
|
||||
/* code changed
|
||||
super(in);
|
||||
target = t;
|
||||
waitTurn();
|
||||
new Thread(this).start();
|
||||
*/
|
||||
}
|
||||
/* code changed to make it work with ImageDecoder architecture
|
||||
static int ThreadLimit = 10;
|
||||
private synchronized static void waitTurn() {
|
||||
try {
|
||||
while(ThreadLimit<=0) PNGImageDecoder.class.wait(1000);
|
||||
} catch(InterruptedException e){}
|
||||
ThreadLimit--;
|
||||
}
|
||||
private synchronized static void endTurn() {
|
||||
if(ThreadLimit<=0) PNGImageDecoder.class.notify();
|
||||
ThreadLimit++;
|
||||
}
|
||||
*/
|
||||
byte[] inbuf = new byte[4096];
|
||||
private void fill() throws IOException {
|
||||
if(!seenEOF) {
|
||||
if(pos>0 && pos<limit) {
|
||||
System.arraycopy(inbuf,pos,inbuf,0,limit-pos);
|
||||
limit = limit-pos;
|
||||
pos = 0;
|
||||
} else if(pos>=limit) {
|
||||
pos = 0; limit = 0;
|
||||
}
|
||||
int bsize = inbuf.length;
|
||||
while(limit<bsize) {
|
||||
int n = underlyingInputStream.read(inbuf,limit,bsize-limit);
|
||||
if(n<=0) { seenEOF=true; break; }
|
||||
limit += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
private boolean need(int n) throws IOException {
|
||||
if(limit-pos>=n) return true;
|
||||
fill();
|
||||
if(limit-pos>=n) return true;
|
||||
if(seenEOF) return false;
|
||||
byte nin[] = new byte[n+100];
|
||||
System.arraycopy(inbuf,pos,nin,0,limit-pos);
|
||||
limit = limit-pos;
|
||||
pos = 0;
|
||||
inbuf = nin;
|
||||
fill();
|
||||
return limit-pos>=n;
|
||||
}
|
||||
private final int getInt(int pos) {
|
||||
return ((inbuf[pos ]&0xFF)<<24)
|
||||
| ((inbuf[pos+1]&0xFF)<<16)
|
||||
| ((inbuf[pos+2]&0xFF)<< 8)
|
||||
| ((inbuf[pos+3]&0xFF) );
|
||||
}
|
||||
private final int getShort(int pos) {
|
||||
return (short)(((inbuf[pos ]&0xFF)<<8)
|
||||
| ((inbuf[pos+1]&0xFF) ));
|
||||
}
|
||||
private final int getByte(int pos) {
|
||||
return inbuf[pos]&0xFF;
|
||||
}
|
||||
private final boolean getChunk() throws IOException {
|
||||
chunkLength = 0;
|
||||
if (!need(8)) return false;
|
||||
chunkLength = getInt(pos);
|
||||
chunkKey = getInt(pos+4);
|
||||
if(chunkLength<0) throw new PNGException("bogus length: "+chunkLength);
|
||||
if (!need(chunkLength+12)) return false;
|
||||
chunkCRC = getInt(pos+8+chunkLength);
|
||||
chunkStart = pos+8;
|
||||
int calcCRC = crc(inbuf,pos+4,chunkLength+4);
|
||||
if(chunkCRC!=calcCRC && checkCRC) throw new PNGException("crc corruption");
|
||||
pos+=chunkLength+12;
|
||||
return true;
|
||||
}
|
||||
private void readAll() throws IOException {
|
||||
while(getChunk()) handleChunk(chunkKey,inbuf,chunkStart,chunkLength);
|
||||
}
|
||||
boolean getData() throws IOException {
|
||||
while(chunkLength==0 && getChunk())
|
||||
if(handleChunk(chunkKey,inbuf,chunkStart,chunkLength))
|
||||
chunkLength = 0;
|
||||
return chunkLength>0;
|
||||
}
|
||||
//abstract protected boolean handleChunk(int key, byte[] buf, int st, int len)
|
||||
// throws IOException;
|
||||
private static boolean checkCRC = true;
|
||||
public static boolean getCheckCRC() { return checkCRC; }
|
||||
public static void setCheckCRC(boolean c) { checkCRC = c; }
|
||||
|
||||
protected void wrc(int c) {
|
||||
c = c&0xFF;
|
||||
if(c<=' '||c>'z') c = '?';
|
||||
System.out.write(c);
|
||||
}
|
||||
protected void wrk(int n) {
|
||||
wrc(n>>24);
|
||||
wrc(n>>16);
|
||||
wrc(n>>8);
|
||||
wrc(n);
|
||||
}
|
||||
public void print() {
|
||||
wrk(chunkKey);
|
||||
System.out.print(" "+chunkLength+"\n");
|
||||
}
|
||||
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
private static final int[] crc_table = new int[256];
|
||||
|
||||
/* Make the table for a fast CRC. */
|
||||
static {
|
||||
for (int n = 0; n < 256; n++) {
|
||||
int c = n;
|
||||
for (int k = 0; k < 8; k++)
|
||||
if ((c & 1) != 0)
|
||||
c = 0xedb88320 ^ (c >>> 1);
|
||||
else
|
||||
c = c >>> 1;
|
||||
crc_table[n] = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
|
||||
should be initialized to all 1's, and the transmitted value
|
||||
is the 1's complement of the final running CRC (see the
|
||||
crc() routine below)). */
|
||||
|
||||
static private int update_crc(int crc, byte[] buf, int offset, int len) {
|
||||
int c = crc;
|
||||
while (--len>=0)
|
||||
c = crc_table[(c ^ buf[offset++]) & 0xff] ^ (c >>> 8);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||
static private int crc(byte[] buf, int offset, int len) {
|
||||
return update_crc(0xffffffff, buf, offset, len) ^ 0xffffffff;
|
||||
}
|
||||
public static class Chromaticities {
|
||||
public float whiteX, whiteY, redX, redY, greenX, greenY, blueX, blueY;
|
||||
Chromaticities(int wx, int wy, int rx, int ry, int gx, int gy, int bx, int by) {
|
||||
whiteX = wx/100000.0f;
|
||||
whiteY = wy/100000.0f;
|
||||
redX = rx/100000.0f;
|
||||
redY = ry/100000.0f;
|
||||
greenX = gx/100000.0f;
|
||||
greenY = gy/100000.0f;
|
||||
blueX = bx/100000.0f;
|
||||
blueY = by/100000.0f;
|
||||
}
|
||||
public String toString() {
|
||||
return "Chromaticities(white="+whiteX+","+whiteY+";red="+
|
||||
redX+","+redY+";green="+
|
||||
greenX+","+greenY+";blue="+
|
||||
blueX+","+blueY+")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the following class are added to make it work with ImageDecoder architecture
|
||||
|
||||
class PNGFilterInputStream extends FilterInputStream {
|
||||
PNGImageDecoder owner;
|
||||
public InputStream underlyingInputStream;
|
||||
public PNGFilterInputStream(PNGImageDecoder owner, InputStream is) {
|
||||
super(is);
|
||||
underlyingInputStream = in;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
return owner.limit-owner.pos+in.available();}
|
||||
public boolean markSupported() { return false; }
|
||||
public int read() throws IOException {
|
||||
if(owner.chunkLength<=0) if(!owner.getData()) return -1;
|
||||
owner.chunkLength--;
|
||||
return owner.inbuf[owner.chunkStart++]&0xFF;
|
||||
}
|
||||
public int read(byte[] b) throws IOException{return read(b,0,b.length);}
|
||||
public int read(byte[] b, int st, int len) throws IOException {
|
||||
if(owner.chunkLength<=0) if(!owner.getData()) return -1;
|
||||
if(owner.chunkLength<len) len = owner.chunkLength;
|
||||
System.arraycopy(owner.inbuf,owner.chunkStart,b,st,len);
|
||||
owner.chunkLength-=len;
|
||||
owner.chunkStart+=len;
|
||||
return len;
|
||||
}
|
||||
public long skip(long n) throws IOException {
|
||||
int i;
|
||||
for(i = 0; i<n && read()>=0; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
447
jdkSrc/jdk8/sun/awt/image/PixelConverter.java
Normal file
447
jdkSrc/jdk8/sun/awt/image/PixelConverter.java
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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 sun.awt.image;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
/**
|
||||
* This class provides utilities for converting between the standard
|
||||
* rgb colorspace specification and the equivalent value for a pixel
|
||||
* of a given surface type. The class was designed for use by the
|
||||
* SurfaceType objects, since the conversion between pixel values
|
||||
* and rgb values is inherently tied to the type of surface we are
|
||||
* dealing with. Some conversions cannot be done automatically,
|
||||
* however (for example, the AnyInt or AnyDCM surface types), so
|
||||
* we require the caller to pass in a ColorModel object so that
|
||||
* we can calculate the pixel values in these generic cases as well.
|
||||
*/
|
||||
public class PixelConverter {
|
||||
|
||||
/**
|
||||
* Default object, used as a fallback for any surface types where
|
||||
* we do not know enough about the surface to calculate the
|
||||
* conversions directly. We use the ColorModel object to assist
|
||||
* us in these cases.
|
||||
*/
|
||||
public static final PixelConverter instance = new PixelConverter();
|
||||
|
||||
|
||||
protected int alphaMask = 0;
|
||||
|
||||
protected PixelConverter() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
Object obj = cm.getDataElements(rgb, null);
|
||||
switch (cm.getTransferType()) {
|
||||
case DataBuffer.TYPE_BYTE:
|
||||
byte[] bytearr = (byte[]) obj;
|
||||
int pix = 0;
|
||||
|
||||
switch(bytearr.length) {
|
||||
default: // bytearr.length >= 4
|
||||
pix = bytearr[3] << 24;
|
||||
// FALLSTHROUGH
|
||||
case 3:
|
||||
pix |= (bytearr[2] & 0xff) << 16;
|
||||
// FALLSTHROUGH
|
||||
case 2:
|
||||
pix |= (bytearr[1] & 0xff) << 8;
|
||||
// FALLSTHROUGH
|
||||
case 1:
|
||||
pix |= (bytearr[0] & 0xff);
|
||||
}
|
||||
|
||||
return pix;
|
||||
case DataBuffer.TYPE_SHORT:
|
||||
case DataBuffer.TYPE_USHORT:
|
||||
short[] shortarr = (short[]) obj;
|
||||
|
||||
return (((shortarr.length > 1) ? shortarr[1] << 16 : 0) |
|
||||
shortarr[0] & 0xffff);
|
||||
case DataBuffer.TYPE_INT:
|
||||
return ((int[]) obj)[0];
|
||||
default:
|
||||
return rgb;
|
||||
}
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
// REMIND: Not yet implemented
|
||||
return pixel;
|
||||
}
|
||||
|
||||
public final int getAlphaMask() {
|
||||
return alphaMask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses of PixelConverter. These subclasses are
|
||||
* specific to surface types where we can definitively
|
||||
* calculate the conversions. Note that some conversions
|
||||
* are lossy; that is, we cannot necessarily convert a
|
||||
* value and then convert it back and wind up with the
|
||||
* original value. For example, an rgb value that has
|
||||
* an alpha != 1 cannot be converted to an Xrgb pixel
|
||||
* without losing the information in the alpha component.
|
||||
*
|
||||
* The conversion strategies associated with the ThreeByte*
|
||||
* and FourByte* surface types swap the components around
|
||||
* due to the ordering used when the bytes are stored. The
|
||||
* low order byte of a packed-byte pixel will be the first
|
||||
* byte stored and the high order byte will be the last byte
|
||||
* stored. For example, the ThreeByteBgr surface type is
|
||||
* associated with an Xrgb conversion object because the
|
||||
* three bytes are stored as follows:
|
||||
* pixels[0] = b; // low order byte of an Xrgb pixel
|
||||
* pixels[1] = g;
|
||||
* pixels[2] = r; // high order byte of an Xrgb pixel
|
||||
*/
|
||||
|
||||
public static class Rgbx extends PixelConverter {
|
||||
public static final PixelConverter instance = new Rgbx();
|
||||
|
||||
private Rgbx() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return (rgb << 8);
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return (0xff000000 | (pixel >> 8));
|
||||
}
|
||||
}
|
||||
public static class Xrgb extends PixelConverter {
|
||||
public static final PixelConverter instance = new Xrgb();
|
||||
|
||||
private Xrgb() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return (0xff000000 | pixel);
|
||||
}
|
||||
}
|
||||
public static class Argb extends PixelConverter {
|
||||
public static final PixelConverter instance = new Argb();
|
||||
|
||||
private Argb() {
|
||||
alphaMask = 0xff000000;
|
||||
}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return pixel;
|
||||
}
|
||||
}
|
||||
public static class Ushort565Rgb extends PixelConverter {
|
||||
public static final PixelConverter instance = new Ushort565Rgb();
|
||||
|
||||
private Ushort565Rgb() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return (((rgb >> (16 + 3 - 11)) & 0xf800) |
|
||||
((rgb >> ( 8 + 2 - 5)) & 0x07e0) |
|
||||
((rgb >> ( 0 + 3 - 0)) & 0x001f));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int r, g, b;
|
||||
r = (pixel >> 11) & 0x1f;
|
||||
r = (r << 3) | (r >> 2);
|
||||
g = (pixel >> 5) & 0x3f;
|
||||
g = (g << 2) | (g >> 4);
|
||||
b = (pixel ) & 0x1f;
|
||||
b = (b << 3) | (b >> 2);
|
||||
return (0xff000000 | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
}
|
||||
public static class Ushort555Rgbx extends PixelConverter {
|
||||
public static final PixelConverter instance = new Ushort555Rgbx();
|
||||
|
||||
private Ushort555Rgbx() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return (((rgb >> (16 + 3 - 11)) & 0xf800) |
|
||||
((rgb >> ( 8 + 3 - 6)) & 0x07c0) |
|
||||
((rgb >> ( 0 + 3 - 1)) & 0x003e));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int r, g, b;
|
||||
r = (pixel >> 11) & 0x1f;
|
||||
r = (r << 3) | (r >> 2);
|
||||
g = (pixel >> 6) & 0x1f;
|
||||
g = (g << 3) | (g >> 2);
|
||||
b = (pixel >> 1) & 0x1f;
|
||||
b = (b << 3) | (b >> 2);
|
||||
return (0xff000000 | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
}
|
||||
public static class Ushort555Rgb extends PixelConverter {
|
||||
public static final PixelConverter instance = new Ushort555Rgb();
|
||||
|
||||
private Ushort555Rgb() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return (((rgb >> (16 + 3 - 10)) & 0x7c00) |
|
||||
((rgb >> ( 8 + 3 - 5)) & 0x03e0) |
|
||||
((rgb >> ( 0 + 3 - 0)) & 0x001f));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int r, g, b;
|
||||
r = (pixel >> 10) & 0x1f;
|
||||
r = (r << 3) | (r >> 2);
|
||||
g = (pixel >> 5) & 0x1f;
|
||||
g = (g << 3) | (g >> 2);
|
||||
b = (pixel ) & 0x1f;
|
||||
b = (b << 3) | (b >> 2);
|
||||
return (0xff000000 | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
}
|
||||
public static class Ushort4444Argb extends PixelConverter {
|
||||
public static final PixelConverter instance = new Ushort4444Argb();
|
||||
|
||||
private Ushort4444Argb() {
|
||||
alphaMask = 0xf000;
|
||||
}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
// use upper 4 bits for each color
|
||||
// 0xAaRrGgBb -> 0x0000ARGB
|
||||
int a = (rgb >> 16) & 0xf000;
|
||||
int r = (rgb >> 12) & 0x0f00;
|
||||
int g = (rgb >> 8) & 0x00f0;
|
||||
int b = (rgb >> 4) & 0x000f;
|
||||
|
||||
return (a | r | g | b);
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int a, r, g, b;
|
||||
// replicate 4 bits for each color
|
||||
// 0xARGB -> 0xAARRGGBB
|
||||
a = pixel & 0xf000;
|
||||
a = ((pixel << 16) | (pixel << 12)) & 0xff000000;
|
||||
r = pixel & 0x0f00;
|
||||
r = ((pixel << 12) | (pixel << 8)) & 0x00ff0000;
|
||||
g = pixel & 0x00f0;
|
||||
g = ((pixel << 8) | (pixel << 4)) & 0x0000ff00;
|
||||
b = pixel & 0x000f;
|
||||
b = ((pixel << 4) | (pixel << 0)) & 0x000000ff;
|
||||
|
||||
return (a | r | g | b);
|
||||
}
|
||||
}
|
||||
public static class Xbgr extends PixelConverter {
|
||||
public static final PixelConverter instance = new Xbgr();
|
||||
|
||||
private Xbgr() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return (((rgb & 0xff) << 16) |
|
||||
(rgb & 0xff00) |
|
||||
((rgb >> 16) & 0xff));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return (0xff000000 |
|
||||
((pixel & 0xff) << 16) |
|
||||
(pixel & 0xff00) |
|
||||
((pixel >> 16) & 0xff));
|
||||
}
|
||||
}
|
||||
public static class Bgrx extends PixelConverter {
|
||||
public static final PixelConverter instance = new Bgrx();
|
||||
|
||||
private Bgrx() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return ((rgb << 24) |
|
||||
((rgb & 0xff00) << 8) |
|
||||
((rgb >> 8) & 0xff00));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return (0xff000000 |
|
||||
((pixel & 0xff00) << 8) |
|
||||
((pixel >> 8) & 0xff00) |
|
||||
(pixel >>> 24));
|
||||
}
|
||||
}
|
||||
public static class Rgba extends PixelConverter {
|
||||
public static final PixelConverter instance = new Rgba();
|
||||
|
||||
private Rgba() {
|
||||
alphaMask = 0x000000ff;
|
||||
}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return ((rgb << 8) | (rgb >>> 24));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return ((pixel << 24) | (pixel >>> 8));
|
||||
}
|
||||
}
|
||||
public static class RgbaPre extends PixelConverter {
|
||||
public static final PixelConverter instance = new RgbaPre();
|
||||
|
||||
private RgbaPre() {
|
||||
alphaMask = 0x000000ff;
|
||||
}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
if ((rgb >> 24) == -1) {
|
||||
return ((rgb << 8) | (rgb >>> 24));
|
||||
}
|
||||
int a = rgb >>> 24;
|
||||
int r = (rgb >> 16) & 0xff;
|
||||
int g = (rgb >> 8) & 0xff;
|
||||
int b = (rgb ) & 0xff;
|
||||
int a2 = a + (a >> 7);
|
||||
r = (r * a2) >> 8;
|
||||
g = (g * a2) >> 8;
|
||||
b = (b * a2) >> 8;
|
||||
return ((r << 24) | (g << 16) | (b << 8) | (a));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int a = pixel & 0xff;
|
||||
if ((a == 0xff) || (a == 0)) {
|
||||
return ((pixel >>> 8) | (pixel << 24));
|
||||
}
|
||||
int r = pixel >>> 24;
|
||||
int g = (pixel >> 16) & 0xff;
|
||||
int b = (pixel >> 8) & 0xff;
|
||||
r = ((r << 8) - r) / a;
|
||||
g = ((g << 8) - g) / a;
|
||||
b = ((b << 8) - b) / a;
|
||||
return ((r << 24) | (g << 16) | (b << 8) | (a));
|
||||
}
|
||||
}
|
||||
public static class ArgbPre extends PixelConverter {
|
||||
public static final PixelConverter instance = new ArgbPre();
|
||||
|
||||
private ArgbPre() {
|
||||
alphaMask = 0xff000000;
|
||||
}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
if ((rgb >> 24) == -1) {
|
||||
return rgb;
|
||||
}
|
||||
int a = rgb >>> 24;
|
||||
int r = (rgb >> 16) & 0xff;
|
||||
int g = (rgb >> 8) & 0xff;
|
||||
int b = (rgb ) & 0xff;
|
||||
int a2 = a + (a >> 7);
|
||||
r = (r * a2) >> 8;
|
||||
g = (g * a2) >> 8;
|
||||
b = (b * a2) >> 8;
|
||||
return ((a << 24) | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int a = pixel >>> 24;
|
||||
if ((a == 0xff) || (a == 0)) {
|
||||
return pixel;
|
||||
}
|
||||
int r = (pixel >> 16) & 0xff;
|
||||
int g = (pixel >> 8) & 0xff;
|
||||
int b = (pixel ) & 0xff;
|
||||
r = ((r << 8) - r) / a;
|
||||
g = ((g << 8) - g) / a;
|
||||
b = ((b << 8) - b) / a;
|
||||
return ((a << 24) | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
}
|
||||
public static class ArgbBm extends PixelConverter {
|
||||
public static final PixelConverter instance = new ArgbBm();
|
||||
|
||||
private ArgbBm() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
return (rgb | ((rgb >> 31) << 24));
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return ((pixel << 7) >> 7);
|
||||
}
|
||||
}
|
||||
public static class ByteGray extends PixelConverter {
|
||||
static final double RED_MULT = 0.299;
|
||||
static final double GRN_MULT = 0.587;
|
||||
static final double BLU_MULT = 0.114;
|
||||
public static final PixelConverter instance = new ByteGray();
|
||||
|
||||
private ByteGray() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
int red = (rgb >> 16) & 0xff;
|
||||
int grn = (rgb >> 8) & 0xff;
|
||||
int blu = (rgb ) & 0xff;
|
||||
return (int) (red * RED_MULT +
|
||||
grn * GRN_MULT +
|
||||
blu * BLU_MULT +
|
||||
0.5);
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel);
|
||||
}
|
||||
}
|
||||
public static class UshortGray extends ByteGray {
|
||||
static final double SHORT_MULT = 257.0; // (65535.0 / 255.0);
|
||||
static final double USHORT_RED_MULT = RED_MULT * SHORT_MULT;
|
||||
static final double USHORT_GRN_MULT = GRN_MULT * SHORT_MULT;
|
||||
static final double USHORT_BLU_MULT = BLU_MULT * SHORT_MULT;
|
||||
public static final PixelConverter instance = new UshortGray();
|
||||
|
||||
private UshortGray() {}
|
||||
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
int red = (rgb >> 16) & 0xff;
|
||||
int grn = (rgb >> 8) & 0xff;
|
||||
int blu = (rgb ) & 0xff;
|
||||
return (int) (red * USHORT_RED_MULT +
|
||||
grn * USHORT_GRN_MULT +
|
||||
blu * USHORT_BLU_MULT +
|
||||
0.5);
|
||||
}
|
||||
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
pixel = pixel >> 8;
|
||||
return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
818
jdkSrc/jdk8/sun/awt/image/ShortBandedRaster.java
Normal file
818
jdkSrc/jdk8/sun/awt/image/ShortBandedRaster.java
Normal file
@@ -0,0 +1,818 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.BandedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferUShort;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of multiple 16-bit
|
||||
* samples stored in separate arrays for each band. Operations on
|
||||
* sets of pixels are performed on a given band of each pixel
|
||||
* in the set before moving on to the next band. The arrays used
|
||||
* for storage may be distinct or shared between some or all of
|
||||
* the bands.
|
||||
* There is only one pixel stride and one scanline stride for all
|
||||
* bands. This type of Raster can be used with a
|
||||
* ComponentColorModel. This class requires a BandedSampleModel.
|
||||
*
|
||||
*/
|
||||
public class ShortBandedRaster extends SunWritableRaster {
|
||||
|
||||
/** Data offsets for each band of image data. */
|
||||
int[] dataOffsets;
|
||||
|
||||
/** Scanline stride of the image data contained in this Raster. */
|
||||
int scanlineStride;
|
||||
|
||||
/** The image data array. */
|
||||
short[][] data;
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
/**
|
||||
* Constructs a ShortBandedRaster with the given SampleModel.
|
||||
* The Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A DataBuffer large enough to describe the
|
||||
* Raster is automatically created. SampleModel must be of type
|
||||
* BandedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specified the origin.
|
||||
*/
|
||||
public ShortBandedRaster(SampleModel sampleModel,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortBandedRaster with the given SampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same size as the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferUShort compatible with SampleModel.
|
||||
* SampleModel must be of type BandedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferUShort that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public ShortBandedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel, dataBuffer,
|
||||
new Rectangle(origin.x, origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortBandedRaster with the given SampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferUShort and
|
||||
* SampleModel must be of type BandedSampleModel.
|
||||
* When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coordinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferUShort that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public ShortBandedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
ShortBandedRaster parent) {
|
||||
|
||||
super(sampleModel, dataBuffer, aRegion, origin, parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
if (!(dataBuffer instanceof DataBufferUShort)) {
|
||||
throw new RasterFormatException("ShortBandedRaster must have " +
|
||||
"ushort DataBuffers");
|
||||
}
|
||||
DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
|
||||
|
||||
if (sampleModel instanceof BandedSampleModel) {
|
||||
BandedSampleModel bsm = (BandedSampleModel)sampleModel;
|
||||
this.scanlineStride = bsm.getScanlineStride();
|
||||
int bankIndices[] = bsm.getBankIndices();
|
||||
int bandOffsets[] = bsm.getBandOffsets();
|
||||
int dOffsets[] = dbus.getOffsets();
|
||||
dataOffsets = new int[bankIndices.length];
|
||||
data = new short[bankIndices.length][];
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
for (int i = 0; i < bankIndices.length; i++) {
|
||||
data[i] = stealData(dbus, bankIndices[i]);
|
||||
dataOffsets[i] = dOffsets[bankIndices[i]] +
|
||||
xOffset + yOffset*scanlineStride + bandOffsets[i];
|
||||
}
|
||||
} else {
|
||||
throw new RasterFormatException("ShortBandedRasters must have "+
|
||||
"BandedSampleModels");
|
||||
}
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data offset
|
||||
* is the index into the band's data array, of the first sample of the
|
||||
* band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[]) dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data offset for the specified band. The data offset
|
||||
* is the index into the band's data array
|
||||
* in which the first sample of the first scanline is stored.
|
||||
* @param The band whose offset is returned.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements between
|
||||
* a given sample and the sample in the same column
|
||||
* of the next row in the same band.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pixel stride, which is always equal to one for
|
||||
* a Raster with a BandedSampleModel.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the entire data array.
|
||||
*/
|
||||
public short[][] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the specific band data array.
|
||||
*/
|
||||
public short[] getDataStorage(int band) {
|
||||
return data[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short outData[];
|
||||
if (obj == null) {
|
||||
outData = new short[numDataElements];
|
||||
} else {
|
||||
outData = (short[])obj;
|
||||
}
|
||||
|
||||
int off = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int band = 0; band < numDataElements; band++) {
|
||||
outData[band] = data[band][dataOffsets[band] + off];
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null);
|
||||
* int numDataElements = Raster.getnumDataElements();
|
||||
* short[] pixel = new short[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short outData[];
|
||||
if (obj == null) {
|
||||
outData = new short[numDataElements*w*h];
|
||||
} else {
|
||||
outData = (short[])obj;
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
short[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
outData[off] = bank[xoff++];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short array of data elements from the specified rectangular
|
||||
* region for the specified band.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = Raster.getShortData(x, y, w, h, null);
|
||||
* // To find the data element at location (x2, y2)
|
||||
* short bandElement = bandData[((y2-y)*w + (x2-x))];
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param band The band to return.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public short[] getShortData(int x, int y, int w, int h,
|
||||
int band, short[] outData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new short[scanlineStride*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[band];
|
||||
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(data[band], yoff, outData, 0, w*h);
|
||||
} else {
|
||||
int off = 0;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(data[band], yoff, outData, off, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = Raster.getShortData(x, y, w, h, null);
|
||||
* int numDataElements = Raster.getnumDataElements();
|
||||
* short[] pixel = new short[numDataElements];
|
||||
* // To find a data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public short[] getShortData(int x, int y, int w, int h,
|
||||
short[] outData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new short[numDataElements*scanlineStride*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
short[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
outData[off] = bank[xoff++];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the data element for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short inData[] = (short[])obj;
|
||||
int off = (y-minY)*scanlineStride + (x-minX);
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
data[i][dataOffsets[i] + off] = inData[i];
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
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.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write inRaster (minX, minY) to (dstX, dstY)
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
Object tdata = null;
|
||||
|
||||
// // REMIND: Do something faster!
|
||||
// if (inRaster instanceof ShortBandedRaster) {
|
||||
// }
|
||||
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
// Grab one scanline at a time
|
||||
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, tdata);
|
||||
setDataElements(dstX, dstY + startY, width, 1, tdata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short inData[] = (short[])obj;
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
short[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
bank[xoff++] = inData[off];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a short array of data elements into the specified
|
||||
* rectangular region for the specified band.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))]
|
||||
* </pre>
|
||||
* @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 band The band to set.
|
||||
* @param inData The data elements to be stored.
|
||||
*/
|
||||
public void putShortData(int x, int y, int w, int h,
|
||||
int band, short[] inData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(inData, 0, data[band], yoff, w*h);
|
||||
} else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(inData, off, data[band], yoff, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a short integer array of data elements into the specified
|
||||
* rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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 The data elements to be stored.
|
||||
*/
|
||||
public void putShortData(int x, int y, int w, int h, short[] inData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride + (x-minX);
|
||||
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
int off = c;
|
||||
short[] bank = data[c];
|
||||
int dataOffset = dataOffsets[c];
|
||||
|
||||
int yoff2 = yoff;
|
||||
for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) {
|
||||
int xoff = dataOffset + yoff2;
|
||||
for (int xstart=0; xstart < w; xstart++) {
|
||||
bank[xoff++] = inData[off];
|
||||
off += numDataElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Writable subRaster given a region of the Raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this Raster to the upper-left corner
|
||||
* of the subRaster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subRaster will reference the same
|
||||
* DataBuffers as the parent Raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent Raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild(int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.minX + this.width)) {
|
||||
throw new RasterFormatException("(x + width) is outside of Raster");
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.minY + this.height)) {
|
||||
throw new RasterFormatException("(y + height) is outside of Raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new ShortBandedRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0, y0, width, height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* DataBuffers as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int bandList[]) {
|
||||
return createWritableChild(x, y, width, height, x0, y0, bandList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w,h);
|
||||
|
||||
return new ShortBandedRaster(sm, new Point(0,0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the Raster is a subRaster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
* Verifies whether the data buffer has enough data for the raster,
|
||||
* taking into account offsets, after ensuring all offsets are >=0.
|
||||
* @throws RasterFormatException if a problem is detected.
|
||||
*/
|
||||
private void verify() {
|
||||
|
||||
/* Need to re-verify the dimensions since a sample model may be
|
||||
* specified to the constructor
|
||||
*/
|
||||
if (width <= 0 || height <= 0 ||
|
||||
height > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
|
||||
if ((long)minX - sampleModelTranslateX < 0 ||
|
||||
(long)minY - sampleModelTranslateY < 0) {
|
||||
|
||||
throw new RasterFormatException("Incorrect origin/translate: (" +
|
||||
minX + ", " + minY + ") / (" +
|
||||
sampleModelTranslateX + ", " + sampleModelTranslateY + ")");
|
||||
}
|
||||
|
||||
if (height > 1 || minY - sampleModelTranslateY > 0) {
|
||||
// buffer should contain at least one scanline
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
if (scanlineStride > data[i].length) {
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure data for Raster is in a legal range
|
||||
for (int i=0; i < dataOffsets.length; i++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band "+i+
|
||||
"("+dataOffsets[i]+
|
||||
") must be >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
if ((width - 1) > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
int lastPixelOffset = lastScanOffset + (width - 1);
|
||||
|
||||
int maxIndex = 0;
|
||||
int index;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
index = lastPixelOffset + dataOffsets[i];
|
||||
if (index > maxIndex) {
|
||||
maxIndex = index;
|
||||
}
|
||||
}
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
if (data[i].length <= maxIndex) {
|
||||
throw new RasterFormatException("Data array too small " +
|
||||
"(should be > "+ maxIndex+" )");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ShortBandedRaster: width = "+width+" height = "
|
||||
+ height
|
||||
+" #numBands " + numBands
|
||||
+" #dataElements "+numDataElements);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
892
jdkSrc/jdk8/sun/awt/image/ShortComponentRaster.java
Normal file
892
jdkSrc/jdk8/sun/awt/image/ShortComponentRaster.java
Normal file
@@ -0,0 +1,892 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferUShort;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of one or more 16-bit
|
||||
* data elements stored in close proximity to each other in a short integer
|
||||
* array. The bit precision per data element is that
|
||||
* of the data type (that is, the bit precision for this Raster is 16).
|
||||
* There is only one pixel stride and one scanline stride for all
|
||||
* bands. This type of Raster can be used with a
|
||||
* ComponentColorModel if there are multiple bands, or a
|
||||
* IndexColorModel if there is only one band.
|
||||
* <p>
|
||||
* For example, 5-6-5 RGB image data can be represented by a
|
||||
* ShortComponentRaster using a SinglePixelPackedSampleModel and
|
||||
* a ComponentColorModel.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ShortComponentRaster extends SunWritableRaster {
|
||||
|
||||
/** private band offset for use by native code */
|
||||
protected int bandOffset;
|
||||
|
||||
/** Data offsets for each band of image data. */
|
||||
protected int[] dataOffsets;
|
||||
|
||||
/** Scanline stride of the image data contained in this Raster. */
|
||||
protected int scanlineStride;
|
||||
|
||||
/** Pixel stride of the image data contained in this Raster. */
|
||||
protected int pixelStride;
|
||||
|
||||
/** The image data array. */
|
||||
protected short[] data;
|
||||
|
||||
int type;
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
static private native void initIDs();
|
||||
static {
|
||||
/* ensure that the necessary native libraries are loaded */
|
||||
NativeLibLoader.loadLibraries();
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortComponentRaster with the given SampleModel.
|
||||
* The Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A DataBuffer large enough to describe the
|
||||
* Raster is automatically created. SampleModel must be of type
|
||||
* ComponentSampleModel or SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specified the origin.
|
||||
*/
|
||||
public ShortComponentRaster(SampleModel sampleModel, Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortComponentRaster with the given SampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same sizes the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferUShort compatible with SampleModel.
|
||||
* SampleModel must be of type ComponentSampleModel or
|
||||
* SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferUShort that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public ShortComponentRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
dataBuffer,
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortComponentRaster with the given SampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferUShort and
|
||||
* SampleModel must be of type ComponentSampleModel or
|
||||
* SinglePixelPackedSampleModel. When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coodinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferUShort that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public ShortComponentRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
ShortComponentRaster parent) {
|
||||
|
||||
super(sampleModel, dataBuffer, aRegion, origin, parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
|
||||
if(!(dataBuffer instanceof DataBufferUShort)) {
|
||||
throw new RasterFormatException("ShortComponentRasters must have "+
|
||||
"short DataBuffers");
|
||||
}
|
||||
|
||||
DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
|
||||
this.data = stealData(dbus, 0);
|
||||
if (dbus.getNumBanks() != 1) {
|
||||
throw new
|
||||
RasterFormatException("DataBuffer for ShortComponentRasters"+
|
||||
" must only have 1 bank.");
|
||||
}
|
||||
int dbOffset = dbus.getOffset();
|
||||
|
||||
if (sampleModel instanceof ComponentSampleModel) {
|
||||
ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
|
||||
this.type = IntegerComponentRaster.TYPE_USHORT_SAMPLES;
|
||||
this.scanlineStride = csm.getScanlineStride();
|
||||
this.pixelStride = csm.getPixelStride();
|
||||
this.dataOffsets = csm.getBandOffsets();
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
for (int i = 0; i < getNumDataElements(); i++) {
|
||||
dataOffsets[i] += dbOffset +
|
||||
xOffset*pixelStride+yOffset*scanlineStride;
|
||||
}
|
||||
} else if (sampleModel instanceof SinglePixelPackedSampleModel) {
|
||||
SinglePixelPackedSampleModel sppsm =
|
||||
(SinglePixelPackedSampleModel)sampleModel;
|
||||
this.type = IntegerComponentRaster.TYPE_USHORT_PACKED_SAMPLES;
|
||||
this.scanlineStride = sppsm.getScanlineStride();
|
||||
this.pixelStride = 1;
|
||||
this.dataOffsets = new int[1];
|
||||
this.dataOffsets[0] = dbOffset;
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
dataOffsets[0] += xOffset+yOffset*scanlineStride;
|
||||
} else {
|
||||
throw new RasterFormatException("ShortComponentRasters must have"+
|
||||
"ComponentSampleModel or SinglePixelPackedSampleModel");
|
||||
}
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data offset
|
||||
* is the index into the band's data array, of the first sample of the
|
||||
* band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[]) dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data offset for the specified band. The data offset
|
||||
* is the index into the data array in which the first sample
|
||||
* of the first scanline is stored.
|
||||
* @param band The band whose offset is returned.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements between
|
||||
* a given sample and the same sample in the same column of the next row.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel stride -- the number of data array elements between two
|
||||
* samples for the same band on the same scanline.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return pixelStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the data array.
|
||||
*/
|
||||
public short[] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short outData[];
|
||||
if (obj == null) {
|
||||
outData = new short[numDataElements];
|
||||
} else {
|
||||
outData = (short[])obj;
|
||||
}
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
for (int band = 0; band < numDataElements; band++) {
|
||||
outData[band] = data[dataOffsets[band] + off];
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* <pre>
|
||||
* short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null);
|
||||
* int numDataElements = Raster.getBands();
|
||||
* short[] pixel = new short[numDataElements];
|
||||
* // To find the data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short outData[];
|
||||
if (obj == null) {
|
||||
outData = new short[w*h*numDataElements];
|
||||
} else {
|
||||
outData = (short[])obj;
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short integer array of data elements from the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = Raster.getShortData(x, y, w, h, null);
|
||||
* // To find the data element at location (x2, y2)
|
||||
* short dataElenent = bandData[((y2-y)*w + (x2-x))];
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the sample rectangle.
|
||||
* @param height Height of the sample rectangle.
|
||||
* @param band The band to return.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public short[] getShortData(int x, int y, int w, int h,
|
||||
int band, short[] outData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new short[numDataElements*w*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride+ dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(data, yoff, outData, 0, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(data, yoff, outData, off, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
outData[off++] = data[xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short integer array of data elements from the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = Raster.getShortData(x, y, w, h, null);
|
||||
* int numDataElements = Raster.getNumBands();
|
||||
* short[] pixel = new short[numDataElements];
|
||||
* // To find the data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public short[] getShortData(int x, int y, int w, int h, short[] outData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new short[numDataElements*w*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the data elements for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short inData[] = (short[])obj;
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
data[dataOffsets[i] + off] = (short) inData[i];
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
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.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write inRaster (minX, minY) to (dstX, dstY)
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
Object tdata = null;
|
||||
|
||||
// // REMIND: Do something faster!
|
||||
// if (inRaster instanceof ShortComponentRaster) {
|
||||
// }
|
||||
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
// Grab one scanline at a time
|
||||
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, tdata);
|
||||
setDataElements(dstX, dstY + startY, width, 1, tdata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short inData[] = (short[])obj;
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = (short) inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a short integer array of data elements into the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))]
|
||||
* </pre>
|
||||
* @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 band The band to set.
|
||||
* @param inData The data elements to be stored.
|
||||
*/
|
||||
public void putShortData(int x, int y, int w, int h,
|
||||
int band, short[] inData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride + dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(inData, 0, data, yoff, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(inData, off, data, yoff, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
data[xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a short integer array of data elements into the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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 The data elements to be stored.
|
||||
*/
|
||||
public void putShortData(int x, int y, int w, int h, short[] inData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* band objects as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0, int[] bandList) {
|
||||
WritableRaster newRaster = createWritableChild(x, y,
|
||||
width, height,
|
||||
x0, y0,
|
||||
bandList);
|
||||
return (Raster) newRaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Writable subRaster given a region of the Raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this Raster to the upper-left corner
|
||||
* of the subRaster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subRaster will reference the same
|
||||
* DataBuffers as the parent Raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent Raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild(int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int[] bandList) {
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside the raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside the raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.minX + this.width)) {
|
||||
throw new RasterFormatException("(x + width) is outside of Raster");
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.minY + this.height)) {
|
||||
throw new RasterFormatException("(y + height) is outside of Raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new ShortComponentRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0, y0, width, height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
|
||||
|
||||
return new ShortComponentRaster(sm, new Point(0, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the Raster is a subRaster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
*
|
||||
* The method verifies whether scanline stride and pixel stride do not
|
||||
* cause an integer overflow during calculation of a position of the pixel
|
||||
* in data buffer. It also verifies whether the data buffer has enough data
|
||||
* to correspond the raster layout attributes.
|
||||
*
|
||||
* @throws RasterFormatException if an integer overflow is detected,
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
protected final void verify() {
|
||||
/* Need to re-verify the dimensions since a sample model may be
|
||||
* specified to the constructor
|
||||
*/
|
||||
if (width <= 0 || height <= 0 ||
|
||||
height > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
throw new RasterFormatException("Invalid raster dimension");
|
||||
}
|
||||
|
||||
for (int i = 0; i < dataOffsets.length; i++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band " + i
|
||||
+ "(" + dataOffsets[i]
|
||||
+ ") must be >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
if ((long)minX - sampleModelTranslateX < 0 ||
|
||||
(long)minY - sampleModelTranslateY < 0) {
|
||||
|
||||
throw new RasterFormatException("Incorrect origin/translate: (" +
|
||||
minX + ", " + minY + ") / (" +
|
||||
sampleModelTranslateX + ", " + sampleModelTranslateY + ")");
|
||||
}
|
||||
|
||||
// we can be sure that width and height are greater than 0
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
|
||||
if (height > 1 || minY - sampleModelTranslateY > 0) {
|
||||
// buffer should contain at least one scanline
|
||||
if (scanlineStride > data.length) {
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
}
|
||||
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
|
||||
if (pixelStride < 0 ||
|
||||
pixelStride > (Integer.MAX_VALUE / width) ||
|
||||
pixelStride > data.length)
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect pixel stride: "
|
||||
+ pixelStride);
|
||||
}
|
||||
int lastPixelOffset = (width - 1) * pixelStride;
|
||||
|
||||
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect raster attributes");
|
||||
}
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
int index;
|
||||
int maxIndex = 0;
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
}
|
||||
|
||||
index = lastPixelOffset + dataOffsets[i];
|
||||
|
||||
if (index > maxIndex) {
|
||||
maxIndex = index;
|
||||
}
|
||||
}
|
||||
if (data.length <= maxIndex) {
|
||||
throw new RasterFormatException("Data array too small (should be > "
|
||||
+ maxIndex + " )");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ShortComponentRaster: width = "+width
|
||||
+" height = " + height
|
||||
+" #numDataElements "+numDataElements);
|
||||
// +" xOff = "+xOffset+" yOff = "+yOffset);
|
||||
}
|
||||
|
||||
}
|
||||
772
jdkSrc/jdk8/sun/awt/image/ShortInterleavedRaster.java
Normal file
772
jdkSrc/jdk8/sun/awt/image/ShortInterleavedRaster.java
Normal file
@@ -0,0 +1,772 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, 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 sun.awt.image;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import java.awt.image.PixelInterleavedSampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferUShort;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* This class defines a Raster with pixels consisting of one or more 16-bit
|
||||
* data elements stored in close proximity to each other in a short integer
|
||||
* array. The bit precision per data element is that
|
||||
* of the data type (that is, the bit precision for this Raster is 16).
|
||||
* There is only one pixel stride and one scanline stride for all
|
||||
* bands. This type of Raster can be used with a
|
||||
* ComponentColorModel if there are multiple bands, or a
|
||||
* IndexColorModel if there is only one band.
|
||||
* <p>
|
||||
* For example, 5-6-5 RGB image data can be represented by a
|
||||
* ShortInterleavedRaster using a SinglePixelPackedSampleModel and
|
||||
* a ComponentColorModel.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ShortInterleavedRaster extends ShortComponentRaster {
|
||||
|
||||
/** A cached copy of minX + width for use in bounds checks. */
|
||||
private int maxX;
|
||||
|
||||
/** A cached copy of minY + height for use in bounds checks. */
|
||||
private int maxY;
|
||||
|
||||
/**
|
||||
* Constructs a ShortInterleavedRaster with the given SampleModel.
|
||||
* The Raster's upper left corner is origin and it is the same
|
||||
* size as the SampleModel. A DataBuffer large enough to describe the
|
||||
* Raster is automatically created. SampleModel must be of type
|
||||
* PixelInterleavedSampleModel or SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param origin The Point that specified the origin.
|
||||
*/
|
||||
public ShortInterleavedRaster(SampleModel sampleModel, Point origin) {
|
||||
this(sampleModel,
|
||||
sampleModel.createDataBuffer(),
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortInterleavedRaster with the given SampleModel
|
||||
* and DataBuffer. The Raster's upper left corner is origin and
|
||||
* it is the same sizes the SampleModel. The DataBuffer is not
|
||||
* initialized and must be a DataBufferUShort compatible with SampleModel.
|
||||
* SampleModel must be of type PixelInterleavedSampleModel or
|
||||
* SinglePixelPackedSampleModel.
|
||||
* @param sampleModel The SampleModel that specifies the layout.
|
||||
* @param dataBuffer The DataBufferUShort that contains the image data.
|
||||
* @param origin The Point that specifies the origin.
|
||||
*/
|
||||
public ShortInterleavedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin) {
|
||||
this(sampleModel,
|
||||
dataBuffer,
|
||||
new Rectangle(origin.x,
|
||||
origin.y,
|
||||
sampleModel.getWidth(),
|
||||
sampleModel.getHeight()),
|
||||
origin,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ShortInterleavedRaster with the given SampleModel,
|
||||
* DataBuffer, and parent. DataBuffer must be a DataBufferUShort and
|
||||
* SampleModel must be of type PixelInterleavedSampleModel or
|
||||
* SinglePixelPackedSampleModel. When translated into the base Raster's
|
||||
* coordinate system, aRegion must be contained by the base Raster.
|
||||
* Origin is the coodinate in the new Raster's coordinate system of
|
||||
* the origin of the base Raster. (The base Raster is the Raster's
|
||||
* ancestor which has no parent.)
|
||||
*
|
||||
* 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 DataBufferUShort that contains the image data.
|
||||
* @param aRegion The Rectangle that specifies the image area.
|
||||
* @param origin The Point that specifies the origin.
|
||||
* @param parent The parent (if any) of this raster.
|
||||
*/
|
||||
public ShortInterleavedRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point origin,
|
||||
ShortInterleavedRaster parent) {
|
||||
|
||||
super(sampleModel, dataBuffer, aRegion, origin, parent);
|
||||
this.maxX = minX + width;
|
||||
this.maxY = minY + height;
|
||||
|
||||
if(!(dataBuffer instanceof DataBufferUShort)) {
|
||||
throw new RasterFormatException("ShortInterleavedRasters must "+
|
||||
"have ushort DataBuffers");
|
||||
}
|
||||
|
||||
DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
|
||||
this.data = stealData(dbus, 0);
|
||||
|
||||
// REMIND: need case for interleaved ComponentSampleModel
|
||||
if ((sampleModel instanceof PixelInterleavedSampleModel) ||
|
||||
(sampleModel instanceof ComponentSampleModel &&
|
||||
sampleModel.getNumBands() == 1)) {
|
||||
ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
|
||||
|
||||
this.scanlineStride = csm.getScanlineStride();
|
||||
this.pixelStride = csm.getPixelStride();
|
||||
this.dataOffsets = csm.getBandOffsets();
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
for (int i = 0; i < getNumDataElements(); i++) {
|
||||
dataOffsets[i] += xOffset*pixelStride+yOffset*scanlineStride;
|
||||
}
|
||||
} else if (sampleModel instanceof SinglePixelPackedSampleModel) {
|
||||
SinglePixelPackedSampleModel sppsm =
|
||||
(SinglePixelPackedSampleModel)sampleModel;
|
||||
this.scanlineStride = sppsm.getScanlineStride();
|
||||
this.pixelStride = 1;
|
||||
this.dataOffsets = new int[1];
|
||||
this.dataOffsets[0] = dbus.getOffset();
|
||||
int xOffset = aRegion.x - origin.x;
|
||||
int yOffset = aRegion.y - origin.y;
|
||||
dataOffsets[0] += xOffset+yOffset*scanlineStride;
|
||||
} else {
|
||||
throw new RasterFormatException("ShortInterleavedRasters must "+
|
||||
"have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"+
|
||||
" or 1 band ComponentSampleModel. Sample model is "+
|
||||
sampleModel);
|
||||
}
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the data offsets array. For each band the data offset
|
||||
* is the index into the band's data array, of the first sample of the
|
||||
* band.
|
||||
*/
|
||||
public int[] getDataOffsets() {
|
||||
return (int[]) dataOffsets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data offset for the specified band. The data offset
|
||||
* is the index into the data array in which the first sample
|
||||
* of the first scanline is stored.
|
||||
* @param band The band whose offset is returned.
|
||||
*/
|
||||
public int getDataOffset(int band) {
|
||||
return dataOffsets[band];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanline stride -- the number of data array elements between
|
||||
* a given sample and the same sample in the same column of the next row.
|
||||
*/
|
||||
public int getScanlineStride() {
|
||||
return scanlineStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel stride -- the number of data array elements between two
|
||||
* samples for the same band on the same scanline.
|
||||
*/
|
||||
public int getPixelStride() {
|
||||
return pixelStride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the data array.
|
||||
*/
|
||||
public short[] getDataStorage() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data elements for all bands at the specified
|
||||
* location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short outData[];
|
||||
if (obj == null) {
|
||||
outData = new short[numDataElements];
|
||||
} else {
|
||||
outData = (short[])obj;
|
||||
}
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
for (int band = 0; band < numDataElements; band++) {
|
||||
outData[band] = data[dataOffsets[band] + off];
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of data elements from the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* <pre>
|
||||
* short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null);
|
||||
* int numDataElements = Raster.getBands();
|
||||
* short[] pixel = new short[numDataElements];
|
||||
* // To find the data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData An object reference to an array of type defined by
|
||||
* getTransferType() and length w*h*getNumDataElements().
|
||||
* If null an array of appropriate type and size will be
|
||||
* allocated.
|
||||
* @return An object reference to an array of type defined by
|
||||
* getTransferType() with the request pixel data.
|
||||
*/
|
||||
public Object getDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short outData[];
|
||||
if (obj == null) {
|
||||
outData = new short[w*h*numDataElements];
|
||||
} else {
|
||||
outData = (short[])obj;
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short integer array of data elements from the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = Raster.getShortData(x, y, w, h, null);
|
||||
* // To find the data element at location (x2, y2)
|
||||
* short dataElenent = bandData[((y2-y)*w + (x2-x))];
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the sample rectangle.
|
||||
* @param height Height of the sample rectangle.
|
||||
* @param band The band to return.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public short[] getShortData(int x, int y, int w, int h,
|
||||
int band, short[] outData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new short[numDataElements*w*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride+ dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(data, yoff, outData, 0, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(data, yoff, outData, off, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
outData[off++] = data[xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short integer array of data elements from the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* <pre>
|
||||
* short[] bandData = Raster.getShortData(x, y, w, h, null);
|
||||
* int numDataElements = Raster.getNumBands();
|
||||
* short[] pixel = new short[numDataElements];
|
||||
* // To find the data element at location (x2, y2)
|
||||
* System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
|
||||
* pixel, 0, numDataElements);
|
||||
* </pre>
|
||||
* @param x The X coordinate of the upper left pixel location.
|
||||
* @param y The Y coordinate of the upper left pixel location.
|
||||
* @param width Width of the pixel rectangle.
|
||||
* @param height Height of the pixel rectangle.
|
||||
* @param outData If non-null, data elements for all bands
|
||||
* at the specified location are returned in this array.
|
||||
* @return Data array with data elements for all bands.
|
||||
*/
|
||||
public short[] getShortData(int x, int y, int w, int h, short[] outData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
if (outData == null) {
|
||||
outData = new short[numDataElements*w*h];
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
outData[off++] = data[dataOffsets[c] + xoff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the data elements for all bands at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinate is out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* @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.
|
||||
*/
|
||||
public void setDataElements(int x, int y, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x >= this.maxX) || (y >= this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short inData[] = (short[])obj;
|
||||
int off = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
data[dataOffsets[i] + off] = (short) inData[i];
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* @param x The X coordinate of the pixel location.
|
||||
* @param y The Y coordinate of the pixel location.
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
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.maxX) || (dstOffY + height > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
|
||||
setDataElements(dstOffX, dstOffY, width, height, inRaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the Raster data at the specified location.
|
||||
* @param dstX The absolute X coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param dstY The absolute Y coordinate of the destination pixel
|
||||
* that will receive a copy of the upper-left pixel of the
|
||||
* inRaster
|
||||
* @param width The number of pixels to store horizontally
|
||||
* @param height The number of pixels to store vertically
|
||||
* @param inRaster Raster of data to place at x,y location.
|
||||
*/
|
||||
private void setDataElements(int dstX, int dstY,
|
||||
int width, int height,
|
||||
Raster inRaster) {
|
||||
// Assume bounds checking has been performed previously
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write inRaster (minX, minY) to (dstX, dstY)
|
||||
|
||||
int srcOffX = inRaster.getMinX();
|
||||
int srcOffY = inRaster.getMinY();
|
||||
Object tdata = null;
|
||||
|
||||
// REMIND: Do something faster!
|
||||
// if (inRaster instanceof ShortInterleavedRaster) {
|
||||
// }
|
||||
|
||||
for (int startY=0; startY < height; startY++) {
|
||||
// Grab one scanline at a time
|
||||
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
|
||||
width, 1, tdata);
|
||||
setDataElements(dstX, dstY + startY, width, 1, tdata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an array of data elements into the specified rectangular
|
||||
* region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* A ClassCastException will be thrown if the input object is non null
|
||||
* and references anything other than an array of transferType.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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+h, y+h.
|
||||
*/
|
||||
public void setDataElements(int x, int y, int w, int h, Object obj) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
short inData[] = (short[])obj;
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = (short) inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a short integer array of data elements into the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))]
|
||||
* </pre>
|
||||
* @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 band The band to set.
|
||||
* @param inData The data elements to be stored.
|
||||
*/
|
||||
public void putShortData(int x, int y, int w, int h,
|
||||
int band, short[] inData) {
|
||||
// Bounds check for 'band' will be performed automatically
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride + dataOffsets[band];
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
if (pixelStride == 1) {
|
||||
if (scanlineStride == w) {
|
||||
System.arraycopy(inData, 0, data, yoff, w*h);
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
System.arraycopy(inData, off, data, yoff, w);
|
||||
off += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
data[xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a short integer array of data elements into the
|
||||
* specified rectangular region.
|
||||
* An ArrayIndexOutOfBounds exception will be thrown at runtime
|
||||
* if the pixel coordinates are out of bounds.
|
||||
* The data elements in the
|
||||
* data array are assumed to be packed. That is, a data element
|
||||
* for the nth band at location (x2, y2) would be found at:
|
||||
* <pre>
|
||||
* inData[((y2-y)*w + (x2-x))*numDataElements + n]
|
||||
* </pre>
|
||||
* @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 The data elements to be stored.
|
||||
*/
|
||||
public void putShortData(int x, int y, int w, int h, short[] inData) {
|
||||
if ((x < this.minX) || (y < this.minY) ||
|
||||
(x + w > this.maxX) || (y + h > this.maxY)) {
|
||||
throw new ArrayIndexOutOfBoundsException
|
||||
("Coordinate out of bounds!");
|
||||
}
|
||||
int yoff = (y-minY)*scanlineStride +
|
||||
(x-minX)*pixelStride;
|
||||
int xoff;
|
||||
int off = 0;
|
||||
int xstart;
|
||||
int ystart;
|
||||
|
||||
for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
|
||||
xoff = yoff;
|
||||
for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
|
||||
for (int c = 0; c < numDataElements; c++) {
|
||||
data[dataOffsets[c] + xoff] = inData[off++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subraster given a region of the raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this raster to the upper-left corner
|
||||
* of the subraster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subraster will reference the same
|
||||
* band objects as the parent raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent raster.
|
||||
*/
|
||||
public Raster createChild (int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0, int[] bandList) {
|
||||
WritableRaster newRaster = createWritableChild(x, y,
|
||||
width, height,
|
||||
x0, y0,
|
||||
bandList);
|
||||
return (Raster) newRaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Writable subRaster given a region of the Raster. The x and y
|
||||
* coordinates specify the horizontal and vertical offsets
|
||||
* from the upper-left corner of this Raster to the upper-left corner
|
||||
* of the subRaster. A subset of the bands of the parent Raster may
|
||||
* be specified. If this is null, then all the bands are present in the
|
||||
* subRaster. A translation to the subRaster may also be specified.
|
||||
* Note that the subRaster will reference the same
|
||||
* DataBuffers as the parent Raster, but using different offsets.
|
||||
* @param x X offset.
|
||||
* @param y Y offset.
|
||||
* @param width Width (in pixels) of the subraster.
|
||||
* @param height Height (in pixels) of the subraster.
|
||||
* @param x0 Translated X origin of the subraster.
|
||||
* @param y0 Translated Y origin of the subraster.
|
||||
* @param bandList Array of band indices.
|
||||
* @exception RasterFormatException
|
||||
* if the specified bounding box is outside of the parent Raster.
|
||||
*/
|
||||
public WritableRaster createWritableChild(int x, int y,
|
||||
int width, int height,
|
||||
int x0, int y0,
|
||||
int[] bandList) {
|
||||
if (x < this.minX) {
|
||||
throw new RasterFormatException("x lies outside the raster");
|
||||
}
|
||||
if (y < this.minY) {
|
||||
throw new RasterFormatException("y lies outside the raster");
|
||||
}
|
||||
if ((x+width < x) || (x+width > this.minX + this.width)) {
|
||||
throw new RasterFormatException("(x + width) is outside of Raster");
|
||||
}
|
||||
if ((y+height < y) || (y+height > this.minY + this.height)) {
|
||||
throw new RasterFormatException("(y + height) is outside of Raster");
|
||||
}
|
||||
|
||||
SampleModel sm;
|
||||
|
||||
if (bandList != null)
|
||||
sm = sampleModel.createSubsetSampleModel(bandList);
|
||||
else
|
||||
sm = sampleModel;
|
||||
|
||||
int deltaX = x0 - x;
|
||||
int deltaY = y0 - y;
|
||||
|
||||
return new ShortInterleavedRaster(sm,
|
||||
dataBuffer,
|
||||
new Rectangle(x0, y0, width, height),
|
||||
new Point(sampleModelTranslateX+deltaX,
|
||||
sampleModelTranslateY+deltaY),
|
||||
this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout but using a different
|
||||
* width and height, and with new zeroed data arrays.
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster(int w, int h) {
|
||||
if (w <= 0 || h <=0) {
|
||||
throw new RasterFormatException("negative "+
|
||||
((w <= 0) ? "width" : "height"));
|
||||
}
|
||||
|
||||
SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
|
||||
|
||||
return new ShortInterleavedRaster(sm, new Point(0, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Raster with the same layout and the same
|
||||
* width and height, and with new zeroed data arrays. If
|
||||
* the Raster is a subRaster, this will call
|
||||
* createCompatibleRaster(width, height).
|
||||
*/
|
||||
public WritableRaster createCompatibleWritableRaster() {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ShortInterleavedRaster: width = "+width
|
||||
+" height = " + height
|
||||
+" #numDataElements "+numDataElements);
|
||||
// +" xOff = "+xOffset+" yOff = "+yOffset);
|
||||
}
|
||||
|
||||
}
|
||||
274
jdkSrc/jdk8/sun/awt/image/SunVolatileImage.java
Normal file
274
jdkSrc/jdk8/sun/awt/image/SunVolatileImage.java
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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.
|
||||
*/
|
||||
|
||||
package sun.awt.image;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.VolatileImage;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceManagerFactory;
|
||||
import sun.java2d.DestSurfaceProvider;
|
||||
import sun.java2d.Surface;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
|
||||
/**
|
||||
* This class is the base implementation of the VolatileImage
|
||||
* abstract class. The class implements most of the standard Image
|
||||
* methods (width, height, etc.) but delegates all surface management
|
||||
* issues to a platform-specific VolatileSurfaceManager. When a new instance
|
||||
* of SunVolatileImage is created, it automatically creates an
|
||||
* appropriate VolatileSurfaceManager for the GraphicsConfiguration
|
||||
* under which this SunVolatileImage was created.
|
||||
*/
|
||||
public class SunVolatileImage extends VolatileImage
|
||||
implements DestSurfaceProvider
|
||||
{
|
||||
|
||||
protected VolatileSurfaceManager volSurfaceManager;
|
||||
protected Component comp;
|
||||
private GraphicsConfiguration graphicsConfig;
|
||||
private Font defaultFont;
|
||||
private int width, height;
|
||||
private int forcedAccelSurfaceType;
|
||||
|
||||
protected SunVolatileImage(Component comp,
|
||||
GraphicsConfiguration graphicsConfig,
|
||||
int width, int height, Object context,
|
||||
int transparency, ImageCapabilities caps,
|
||||
int accType)
|
||||
{
|
||||
this.comp = comp;
|
||||
this.graphicsConfig = graphicsConfig;
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException("Width (" + width + ")" +
|
||||
" and height (" + height + ") cannot be <= 0");
|
||||
}
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.forcedAccelSurfaceType = accType;
|
||||
if (!(transparency == Transparency.OPAQUE ||
|
||||
transparency == Transparency.BITMASK ||
|
||||
transparency == Transparency.TRANSLUCENT))
|
||||
{
|
||||
throw new IllegalArgumentException("Unknown transparency type:" +
|
||||
transparency);
|
||||
}
|
||||
this.transparency = transparency;
|
||||
this.volSurfaceManager = createSurfaceManager(context, caps);
|
||||
SurfaceManager.setManager(this, volSurfaceManager);
|
||||
|
||||
// post-construction initialization of the surface manager
|
||||
volSurfaceManager.initialize();
|
||||
// clear the background
|
||||
volSurfaceManager.initContents();
|
||||
}
|
||||
|
||||
private SunVolatileImage(Component comp,
|
||||
GraphicsConfiguration graphicsConfig,
|
||||
int width, int height, Object context,
|
||||
ImageCapabilities caps)
|
||||
{
|
||||
this(comp, graphicsConfig,
|
||||
width, height, context, Transparency.OPAQUE, caps, UNDEFINED);
|
||||
}
|
||||
|
||||
public SunVolatileImage(Component comp, int width, int height) {
|
||||
this(comp, width, height, null);
|
||||
}
|
||||
|
||||
public SunVolatileImage(Component comp,
|
||||
int width, int height, Object context)
|
||||
{
|
||||
this(comp, comp.getGraphicsConfiguration(),
|
||||
width, height, context, null);
|
||||
}
|
||||
|
||||
public SunVolatileImage(GraphicsConfiguration graphicsConfig,
|
||||
int width, int height, int transparency,
|
||||
ImageCapabilities caps)
|
||||
{
|
||||
this(null, graphicsConfig, width, height, null, transparency,
|
||||
caps, UNDEFINED);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public GraphicsConfiguration getGraphicsConfig() {
|
||||
return graphicsConfig;
|
||||
}
|
||||
|
||||
public void updateGraphicsConfig() {
|
||||
// If this VImage is associated with a Component, get an updated
|
||||
// graphicsConfig from that component. Otherwise, keep the one
|
||||
// that we were created with
|
||||
if (comp != null) {
|
||||
GraphicsConfiguration gc = comp.getGraphicsConfiguration();
|
||||
if (gc != null) {
|
||||
// Could potentially be null in some failure situations;
|
||||
// better to keep the old non-null value around than to
|
||||
// set graphicsConfig to null
|
||||
graphicsConfig = gc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
return comp;
|
||||
}
|
||||
|
||||
public int getForcedAccelSurfaceType() {
|
||||
return forcedAccelSurfaceType;
|
||||
}
|
||||
|
||||
protected VolatileSurfaceManager createSurfaceManager(Object context,
|
||||
ImageCapabilities caps)
|
||||
{
|
||||
/**
|
||||
* Platform-specific SurfaceManagerFactories will return a
|
||||
* manager suited to acceleration on each platform. But if
|
||||
* the user is asking for a VolatileImage from a BufferedImageGC,
|
||||
* then we need to return the appropriate unaccelerated manager.
|
||||
* Note: this could change in the future; if some platform would
|
||||
* like to accelerate BIGC volatile images, then this special-casing
|
||||
* of the BIGC graphicsConfig should live in platform-specific
|
||||
* code instead.
|
||||
* We do the same for a Printer Device, and if user requested an
|
||||
* unaccelerated VolatileImage by passing the capabilities object.
|
||||
*/
|
||||
if (graphicsConfig instanceof BufferedImageGraphicsConfig ||
|
||||
graphicsConfig instanceof sun.print.PrinterGraphicsConfig ||
|
||||
(caps != null && !caps.isAccelerated()))
|
||||
{
|
||||
return new BufImgVolatileSurfaceManager(this, context);
|
||||
}
|
||||
SurfaceManagerFactory smf = SurfaceManagerFactory.getInstance();
|
||||
return smf.createVolatileManager(this, context);
|
||||
}
|
||||
|
||||
private Color getForeground() {
|
||||
if (comp != null) {
|
||||
return comp.getForeground();
|
||||
} else {
|
||||
return Color.black;
|
||||
}
|
||||
}
|
||||
|
||||
private Color getBackground() {
|
||||
if (comp != null) {
|
||||
return comp.getBackground();
|
||||
} else {
|
||||
return Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
private Font getFont() {
|
||||
if (comp != null) {
|
||||
return comp.getFont();
|
||||
} else {
|
||||
if (defaultFont == null) {
|
||||
defaultFont = new Font("Dialog", Font.PLAIN, 12);
|
||||
}
|
||||
return defaultFont;
|
||||
}
|
||||
}
|
||||
|
||||
public Graphics2D createGraphics() {
|
||||
return new SunGraphics2D(volSurfaceManager.getPrimarySurfaceData(),
|
||||
getForeground(),
|
||||
getBackground(),
|
||||
getFont());
|
||||
}
|
||||
|
||||
// Image method implementations
|
||||
public Object getProperty(String name, ImageObserver observer) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("null property name is not allowed");
|
||||
}
|
||||
return java.awt.Image.UndefinedProperty;
|
||||
}
|
||||
|
||||
public int getWidth(ImageObserver observer) {
|
||||
return getWidth();
|
||||
}
|
||||
|
||||
public int getHeight(ImageObserver observer) {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a BufferedImage intended for use as a "snapshot"
|
||||
* or a backup surface.
|
||||
*/
|
||||
public BufferedImage getBackupImage() {
|
||||
return graphicsConfig.createCompatibleImage(getWidth(), getHeight(),
|
||||
getTransparency());
|
||||
}
|
||||
|
||||
public BufferedImage getSnapshot() {
|
||||
BufferedImage bi = getBackupImage();
|
||||
Graphics2D g = bi.createGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(this, 0, 0, null);
|
||||
g.dispose();
|
||||
return bi;
|
||||
}
|
||||
|
||||
public int validate(GraphicsConfiguration gc) {
|
||||
return volSurfaceManager.validate(gc);
|
||||
}
|
||||
|
||||
public boolean contentsLost() {
|
||||
return volSurfaceManager.contentsLost();
|
||||
}
|
||||
|
||||
public ImageCapabilities getCapabilities() {
|
||||
return volSurfaceManager.getCapabilities(graphicsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.DestSurfaceProvider#getDestSurface
|
||||
*/
|
||||
@Override
|
||||
public Surface getDestSurface() {
|
||||
return volSurfaceManager.getPrimarySurfaceData();
|
||||
}
|
||||
}
|
||||
139
jdkSrc/jdk8/sun/awt/image/SunWritableRaster.java
Normal file
139
jdkSrc/jdk8/sun/awt/image/SunWritableRaster.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 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.
|
||||
*/
|
||||
|
||||
package sun.awt.image;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.image.DataBufferUShort;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
import sun.java2d.StateTrackable.State;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.StateTrackableDelegate;
|
||||
|
||||
/**
|
||||
* This class exists as a middle layer between WritableRaster and its
|
||||
* implementation specific subclasses (ByteComponentRaster, ShortBandedRaster,
|
||||
* etc).
|
||||
* It provides utilities to steal the data arrays from the standard DataBuffer
|
||||
* types and also steals the StateTrackableDelegate from the associated
|
||||
* DataBuffer so that it can be updated when the data is changed.
|
||||
*/
|
||||
public class SunWritableRaster extends WritableRaster {
|
||||
private static DataStealer stealer;
|
||||
|
||||
public static interface DataStealer {
|
||||
public byte[] getData(DataBufferByte dbb, int bank);
|
||||
public short[] getData(DataBufferUShort dbus, int bank);
|
||||
public int[] getData(DataBufferInt dbi, int bank);
|
||||
public StateTrackableDelegate getTrackable(DataBuffer db);
|
||||
public void setTrackable(DataBuffer db, StateTrackableDelegate trackable);
|
||||
}
|
||||
|
||||
public static void setDataStealer(DataStealer ds) {
|
||||
if (stealer != null) {
|
||||
throw new InternalError("Attempt to set DataStealer twice");
|
||||
}
|
||||
stealer = ds;
|
||||
}
|
||||
|
||||
public static byte[] stealData(DataBufferByte dbb, int bank) {
|
||||
return stealer.getData(dbb, bank);
|
||||
}
|
||||
|
||||
public static short[] stealData(DataBufferUShort dbus, int bank) {
|
||||
return stealer.getData(dbus, bank);
|
||||
}
|
||||
|
||||
public static int[] stealData(DataBufferInt dbi, int bank) {
|
||||
return stealer.getData(dbi, bank);
|
||||
}
|
||||
|
||||
public static StateTrackableDelegate stealTrackable(DataBuffer db) {
|
||||
return stealer.getTrackable(db);
|
||||
}
|
||||
|
||||
public static void setTrackable(DataBuffer db, StateTrackableDelegate trackable) {
|
||||
stealer.setTrackable(db, trackable);
|
||||
}
|
||||
|
||||
public static void makeTrackable(DataBuffer db) {
|
||||
stealer.setTrackable(db, StateTrackableDelegate.createInstance(State.STABLE));
|
||||
}
|
||||
|
||||
public static void markDirty(DataBuffer db) {
|
||||
stealer.getTrackable(db).markDirty();
|
||||
}
|
||||
|
||||
public static void markDirty(WritableRaster wr) {
|
||||
if (wr instanceof SunWritableRaster) {
|
||||
((SunWritableRaster) wr).markDirty();
|
||||
} else {
|
||||
markDirty(wr.getDataBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
public static void markDirty(Image img) {
|
||||
SurfaceData.getPrimarySurfaceData(img).markDirty();
|
||||
}
|
||||
|
||||
private StateTrackableDelegate theTrackable;
|
||||
|
||||
public SunWritableRaster(SampleModel sampleModel, Point origin) {
|
||||
super(sampleModel, origin);
|
||||
theTrackable = stealTrackable(dataBuffer);
|
||||
}
|
||||
|
||||
public SunWritableRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Point origin)
|
||||
{
|
||||
super(sampleModel, dataBuffer, origin);
|
||||
theTrackable = stealTrackable(dataBuffer);
|
||||
}
|
||||
|
||||
public SunWritableRaster(SampleModel sampleModel,
|
||||
DataBuffer dataBuffer,
|
||||
Rectangle aRegion,
|
||||
Point sampleModelTranslate,
|
||||
WritableRaster parent)
|
||||
{
|
||||
super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent);
|
||||
theTrackable = stealTrackable(dataBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the TrackableDelegate of the associated DataBuffer dirty.
|
||||
*/
|
||||
public final void markDirty() {
|
||||
theTrackable.markDirty();
|
||||
}
|
||||
}
|
||||
305
jdkSrc/jdk8/sun/awt/image/SurfaceManager.java
Normal file
305
jdkSrc/jdk8/sun/awt/image/SurfaceManager.java
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Iterator;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
/**
|
||||
* The abstract base class that manages the various SurfaceData objects that
|
||||
* represent an Image's contents. Subclasses can customize how the surfaces
|
||||
* are organized, whether to cache the original contents in an accelerated
|
||||
* surface, and so on.
|
||||
* <p>
|
||||
* The SurfaceManager also maintains an arbitrary "cache" mechanism which
|
||||
* allows other agents to store data in it specific to their use of this
|
||||
* image. The most common use of the caching mechanism is for destination
|
||||
* SurfaceData objects to store cached copies of the source image.
|
||||
*/
|
||||
public abstract class SurfaceManager {
|
||||
|
||||
public static abstract class ImageAccessor {
|
||||
public abstract SurfaceManager getSurfaceManager(Image img);
|
||||
public abstract void setSurfaceManager(Image img, SurfaceManager mgr);
|
||||
}
|
||||
|
||||
private static ImageAccessor imgaccessor;
|
||||
|
||||
public static void setImageAccessor(ImageAccessor ia) {
|
||||
if (imgaccessor != null) {
|
||||
throw new InternalError("Attempt to set ImageAccessor twice");
|
||||
}
|
||||
imgaccessor = ia;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SurfaceManager object contained within the given Image.
|
||||
*/
|
||||
public static SurfaceManager getManager(Image img) {
|
||||
SurfaceManager sMgr = imgaccessor.getSurfaceManager(img);
|
||||
if (sMgr == null) {
|
||||
/*
|
||||
* In practice only a BufferedImage will get here.
|
||||
*/
|
||||
try {
|
||||
BufferedImage bi = (BufferedImage) img;
|
||||
sMgr = new BufImgSurfaceManager(bi);
|
||||
setManager(bi, sMgr);
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalArgumentException("Invalid Image variant");
|
||||
}
|
||||
}
|
||||
return sMgr;
|
||||
}
|
||||
|
||||
public static void setManager(Image img, SurfaceManager mgr) {
|
||||
imgaccessor.setSurfaceManager(img, mgr);
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<Object,Object> cacheMap;
|
||||
|
||||
/**
|
||||
* Return an arbitrary cached object for an arbitrary cache key.
|
||||
* Other objects can use this mechanism to store cached data about
|
||||
* the source image that will let them save time when using or
|
||||
* manipulating the image in the future.
|
||||
* <p>
|
||||
* Note that the cache is maintained as a simple Map with no
|
||||
* attempts to keep it up to date or invalidate it so any data
|
||||
* stored here must either not be dependent on the state of the
|
||||
* image or it must be individually tracked to see if it is
|
||||
* outdated or obsolete.
|
||||
* <p>
|
||||
* The SurfaceData object of the primary (destination) surface
|
||||
* has a StateTracker mechanism which can help track the validity
|
||||
* and "currentness" of any data stored here.
|
||||
* For convenience and expediency an object stored as cached
|
||||
* data may implement the FlushableCacheData interface specified
|
||||
* below so that it may be notified immediately if the flush()
|
||||
* method is ever called.
|
||||
*/
|
||||
public Object getCacheData(Object key) {
|
||||
return (cacheMap == null) ? null : cacheMap.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an arbitrary cached object for an arbitrary cache key.
|
||||
* See the getCacheData() method for notes on tracking the
|
||||
* validity of data stored using this mechanism.
|
||||
*/
|
||||
public void setCacheData(Object key, Object value) {
|
||||
if (cacheMap == null) {
|
||||
synchronized (this) {
|
||||
if (cacheMap == null) {
|
||||
cacheMap = new ConcurrentHashMap<>(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheMap.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main SurfaceData object that "owns" the pixels for
|
||||
* this SurfaceManager. This SurfaceData is used as the destination
|
||||
* surface in a rendering operation and is the most authoritative
|
||||
* storage for the current state of the pixels, though other
|
||||
* versions might be cached in other locations for efficiency.
|
||||
*/
|
||||
public abstract SurfaceData getPrimarySurfaceData();
|
||||
|
||||
/**
|
||||
* Restores the primary surface being managed, and then returns the
|
||||
* replacement surface. This is called when an accelerated surface has
|
||||
* been "lost", in an attempt to auto-restore its contents.
|
||||
*/
|
||||
public abstract SurfaceData restoreContents();
|
||||
|
||||
/**
|
||||
* Notification that any accelerated surfaces associated with this manager
|
||||
* have been "lost", which might mean that they need to be manually
|
||||
* restored or recreated.
|
||||
*
|
||||
* The default implementation does nothing, but platform-specific
|
||||
* variants which have accelerated surfaces should perform any necessary
|
||||
* actions.
|
||||
*/
|
||||
public void acceleratedSurfaceLost() {}
|
||||
|
||||
/**
|
||||
* Returns an ImageCapabilities object which can be
|
||||
* inquired as to the specific capabilities of this
|
||||
* Image. The capabilities object will return true for
|
||||
* isAccelerated() if the image has a current and valid
|
||||
* SurfaceDataProxy object cached for the specified
|
||||
* GraphicsConfiguration parameter.
|
||||
* <p>
|
||||
* This class provides a default implementation of the
|
||||
* ImageCapabilities that will try to determine if there
|
||||
* is an associated SurfaceDataProxy object and if it is
|
||||
* up to date, but only works for GraphicsConfiguration
|
||||
* objects which implement the ProxiedGraphicsConfig
|
||||
* interface defined below. In practice, all configs
|
||||
* which can be accelerated are currently implementing
|
||||
* that interface.
|
||||
* <p>
|
||||
* A null GraphicsConfiguration returns a value based on whether the
|
||||
* image is currently accelerated on its default GraphicsConfiguration.
|
||||
*
|
||||
* @see java.awt.Image#getCapabilities
|
||||
* @since 1.5
|
||||
*/
|
||||
public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
|
||||
return new ImageCapabilitiesGc(gc);
|
||||
}
|
||||
|
||||
class ImageCapabilitiesGc extends ImageCapabilities {
|
||||
GraphicsConfiguration gc;
|
||||
|
||||
public ImageCapabilitiesGc(GraphicsConfiguration gc) {
|
||||
super(false);
|
||||
this.gc = gc;
|
||||
}
|
||||
|
||||
public boolean isAccelerated() {
|
||||
// Note that when img.getAccelerationPriority() gets set to 0
|
||||
// we remove SurfaceDataProxy objects from the cache and the
|
||||
// answer will be false.
|
||||
GraphicsConfiguration tmpGc = gc;
|
||||
if (tmpGc == null) {
|
||||
tmpGc = GraphicsEnvironment.getLocalGraphicsEnvironment().
|
||||
getDefaultScreenDevice().getDefaultConfiguration();
|
||||
}
|
||||
if (tmpGc instanceof ProxiedGraphicsConfig) {
|
||||
Object proxyKey =
|
||||
((ProxiedGraphicsConfig) tmpGc).getProxyKey();
|
||||
if (proxyKey != null) {
|
||||
SurfaceDataProxy sdp =
|
||||
(SurfaceDataProxy) getCacheData(proxyKey);
|
||||
return (sdp != null && sdp.isAccelerated());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for GraphicsConfiguration objects to implement if
|
||||
* their surfaces accelerate images using SurfaceDataProxy objects.
|
||||
*
|
||||
* Implementing this interface facilitates the default
|
||||
* implementation of getImageCapabilities() above.
|
||||
*/
|
||||
public static interface ProxiedGraphicsConfig {
|
||||
/**
|
||||
* Return the key that destination surfaces created on the
|
||||
* given GraphicsConfiguration use to store SurfaceDataProxy
|
||||
* objects for their cached copies.
|
||||
*/
|
||||
public Object getProxyKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases system resources in use by ancillary SurfaceData objects,
|
||||
* such as surfaces cached in accelerated memory. Subclasses should
|
||||
* override to release any of their flushable data.
|
||||
* <p>
|
||||
* The default implementation will visit all of the value objects
|
||||
* in the cacheMap and flush them if they implement the
|
||||
* FlushableCacheData interface.
|
||||
*/
|
||||
public synchronized void flush() {
|
||||
flush(false);
|
||||
}
|
||||
|
||||
synchronized void flush(boolean deaccelerate) {
|
||||
if (cacheMap != null) {
|
||||
Iterator<Object> i = cacheMap.values().iterator();
|
||||
while (i.hasNext()) {
|
||||
Object o = i.next();
|
||||
if (o instanceof FlushableCacheData) {
|
||||
if (((FlushableCacheData) o).flush(deaccelerate)) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for Objects used in the SurfaceManager cache
|
||||
* to implement if they have data that should be flushed when
|
||||
* the Image is flushed.
|
||||
*/
|
||||
public static interface FlushableCacheData {
|
||||
/**
|
||||
* Flush all cached resources.
|
||||
* The deaccelerated parameter indicates if the flush is
|
||||
* happening because the associated surface is no longer
|
||||
* being accelerated (for instance the acceleration priority
|
||||
* is set below the threshold needed for acceleration).
|
||||
* Returns a boolean that indicates if the cached object is
|
||||
* no longer needed and should be removed from the cache.
|
||||
*/
|
||||
public boolean flush(boolean deaccelerated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when image's acceleration priority is changed.
|
||||
* <p>
|
||||
* The default implementation will visit all of the value objects
|
||||
* in the cacheMap when the priority gets set to 0.0 and flush them
|
||||
* if they implement the FlushableCacheData interface.
|
||||
*/
|
||||
public void setAccelerationPriority(float priority) {
|
||||
if (priority == 0.0f) {
|
||||
flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a scale factor of the image. This is utility method, which
|
||||
* fetches information from the SurfaceData of the image.
|
||||
*
|
||||
* @see SurfaceData#getDefaultScale
|
||||
*/
|
||||
public static int getImageScale(final Image img) {
|
||||
if (!(img instanceof VolatileImage)) {
|
||||
return 1;
|
||||
}
|
||||
final SurfaceManager sm = getManager(img);
|
||||
return sm.getPrimarySurfaceData().getDefaultScale();
|
||||
}
|
||||
}
|
||||
331
jdkSrc/jdk8/sun/awt/image/ToolkitImage.java
Normal file
331
jdkSrc/jdk8/sun/awt/image/ToolkitImage.java
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* 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 sun.awt.image;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.ImageConsumer;
|
||||
import java.awt.image.ImageObserver;
|
||||
import sun.awt.image.ImageRepresentation;
|
||||
import sun.awt.image.FileImageSource;
|
||||
|
||||
public class ToolkitImage extends Image {
|
||||
|
||||
/**
|
||||
* The object which is used to reconstruct the original image data
|
||||
* as needed.
|
||||
*/
|
||||
ImageProducer source;
|
||||
|
||||
InputStreamImageSource src;
|
||||
|
||||
ImageRepresentation imagerep;
|
||||
|
||||
static {
|
||||
/* ensure that the necessary native libraries are loaded */
|
||||
NativeLibLoader.loadLibraries();
|
||||
}
|
||||
|
||||
protected ToolkitImage() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an image from an ImageProducer object.
|
||||
*/
|
||||
public ToolkitImage(ImageProducer is) {
|
||||
source = is;
|
||||
if (is instanceof InputStreamImageSource) {
|
||||
src = (InputStreamImageSource) is;
|
||||
}
|
||||
}
|
||||
|
||||
public ImageProducer getSource() {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private Hashtable properties;
|
||||
|
||||
private int availinfo;
|
||||
|
||||
/**
|
||||
* Return the width of the original image source.
|
||||
* If the width isn't known, then the image is reconstructed.
|
||||
*/
|
||||
public int getWidth() {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.WIDTH) == 0) {
|
||||
reconstruct(ImageObserver.WIDTH);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width of the original image source.
|
||||
* If the width isn't known, then the ImageObserver object will be
|
||||
* notified when the data is available.
|
||||
*/
|
||||
public synchronized int getWidth(ImageObserver iw) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.WIDTH) == 0) {
|
||||
addWatcher(iw, true);
|
||||
if ((availinfo & ImageObserver.WIDTH) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the original image source.
|
||||
* If the height isn't known, then the image is reconstructed.
|
||||
*/
|
||||
public int getHeight() {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.HEIGHT) == 0) {
|
||||
reconstruct(ImageObserver.HEIGHT);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the original image source.
|
||||
* If the height isn't known, then the ImageObserver object will be
|
||||
* notified when the data is available.
|
||||
*/
|
||||
public synchronized int getHeight(ImageObserver iw) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.HEIGHT) == 0) {
|
||||
addWatcher(iw, true);
|
||||
if ((availinfo & ImageObserver.HEIGHT) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a property of the image by name. Individual property names
|
||||
* are defined by the various image formats. If a property is not
|
||||
* defined for a particular image, then this method will return the
|
||||
* UndefinedProperty object. If the properties for this image are
|
||||
* not yet known, then this method will return null and the ImageObserver
|
||||
* object will be notified later. The property name "comment" should
|
||||
* be used to store an optional comment which can be presented to
|
||||
* the user as a description of the image, its source, or its author.
|
||||
*/
|
||||
public Object getProperty(String name, ImageObserver observer) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("null property name is not allowed");
|
||||
}
|
||||
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if (properties == null) {
|
||||
addWatcher(observer, true);
|
||||
if (properties == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Object o = properties.get(name);
|
||||
if (o == null) {
|
||||
o = Image.UndefinedProperty;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
public boolean hasError() {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
return (availinfo & ImageObserver.ERROR) != 0;
|
||||
}
|
||||
|
||||
public int check(ImageObserver iw) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) == 0 &&
|
||||
((~availinfo) & (ImageObserver.WIDTH |
|
||||
ImageObserver.HEIGHT |
|
||||
ImageObserver.PROPERTIES)) != 0) {
|
||||
addWatcher(iw, false);
|
||||
}
|
||||
return availinfo;
|
||||
}
|
||||
|
||||
public void preload(ImageObserver iw) {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if ((availinfo & ImageObserver.ALLBITS) == 0) {
|
||||
addWatcher(iw, true);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void addWatcher(ImageObserver iw, boolean load) {
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
if (iw != null) {
|
||||
iw.imageUpdate(this, ImageObserver.ERROR|ImageObserver.ABORT,
|
||||
-1, -1, -1, -1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ImageRepresentation ir = getImageRep();
|
||||
ir.addWatcher(iw);
|
||||
if (load) {
|
||||
ir.startProduction();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void reconstruct(int flags) {
|
||||
if ((flags & ~availinfo) != 0) {
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
return;
|
||||
}
|
||||
ImageRepresentation ir = getImageRep();
|
||||
ir.startProduction();
|
||||
while ((flags & ~availinfo) != 0) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
if ((availinfo & ImageObserver.ERROR) != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void addInfo(int newinfo) {
|
||||
availinfo |= newinfo;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
void setDimensions(int w, int h) {
|
||||
width = w;
|
||||
height = h;
|
||||
addInfo(ImageObserver.WIDTH | ImageObserver.HEIGHT);
|
||||
}
|
||||
|
||||
void setProperties(Hashtable props) {
|
||||
if (props == null) {
|
||||
props = new Hashtable();
|
||||
}
|
||||
properties = props;
|
||||
addInfo(ImageObserver.PROPERTIES);
|
||||
}
|
||||
|
||||
synchronized void infoDone(int status) {
|
||||
if (status == ImageConsumer.IMAGEERROR ||
|
||||
((~availinfo) & (ImageObserver.WIDTH |
|
||||
ImageObserver.HEIGHT)) != 0) {
|
||||
addInfo(ImageObserver.ERROR);
|
||||
} else if ((availinfo & ImageObserver.PROPERTIES) == 0) {
|
||||
setProperties(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
|
||||
ImageRepresentation ir;
|
||||
synchronized (this) {
|
||||
availinfo &= ~ImageObserver.ERROR;
|
||||
ir = imagerep;
|
||||
imagerep = null;
|
||||
}
|
||||
if (ir != null) {
|
||||
ir.abort();
|
||||
}
|
||||
if (src != null) {
|
||||
src.flush();
|
||||
}
|
||||
}
|
||||
|
||||
protected ImageRepresentation makeImageRep() {
|
||||
return new ImageRepresentation(this, ColorModel.getRGBdefault(),
|
||||
false);
|
||||
}
|
||||
|
||||
public synchronized ImageRepresentation getImageRep() {
|
||||
if (src != null) {
|
||||
src.checkSecurity(null, false);
|
||||
}
|
||||
if (imagerep == null) {
|
||||
imagerep = makeImageRep();
|
||||
}
|
||||
return imagerep;
|
||||
}
|
||||
|
||||
public Graphics getGraphics() {
|
||||
throw new UnsupportedOperationException("getGraphics() not valid for images " +
|
||||
"created with createImage(producer)");
|
||||
}
|
||||
|
||||
/* this method is needed by printing code */
|
||||
public ColorModel getColorModel() {
|
||||
ImageRepresentation imageRep = getImageRep();
|
||||
return imageRep.getColorModel();
|
||||
}
|
||||
|
||||
/* this method is needed by printing code */
|
||||
public BufferedImage getBufferedImage() {
|
||||
ImageRepresentation imageRep = getImageRep();
|
||||
return imageRep.getBufferedImage();
|
||||
}
|
||||
|
||||
public void setAccelerationPriority(float priority) {
|
||||
super.setAccelerationPriority(priority);
|
||||
ImageRepresentation imageRep = getImageRep();
|
||||
imageRep.setAccelerationPriority(accelerationPriority);
|
||||
}
|
||||
}
|
||||
175
jdkSrc/jdk8/sun/awt/image/URLImageSource.java
Normal file
175
jdkSrc/jdk8/sun/awt/image/URLImageSource.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 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 sun.awt.image;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import sun.net.util.URLUtil;
|
||||
|
||||
public class URLImageSource extends InputStreamImageSource {
|
||||
URL url;
|
||||
URLConnection conn;
|
||||
String actualHost;
|
||||
int actualPort;
|
||||
|
||||
public URLImageSource(URL u) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
try {
|
||||
java.security.Permission perm =
|
||||
URLUtil.getConnectPermission(u);
|
||||
if (perm != null) {
|
||||
try {
|
||||
sm.checkPermission(perm);
|
||||
} catch (SecurityException se) {
|
||||
// fallback to checkRead/checkConnect for pre 1.2
|
||||
// security managers
|
||||
if ((perm instanceof java.io.FilePermission) &&
|
||||
perm.getActions().indexOf("read") != -1) {
|
||||
sm.checkRead(perm.getName());
|
||||
} else if ((perm instanceof
|
||||
java.net.SocketPermission) &&
|
||||
perm.getActions().indexOf("connect") != -1) {
|
||||
sm.checkConnect(u.getHost(), u.getPort());
|
||||
} else {
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (java.io.IOException ioe) {
|
||||
sm.checkConnect(u.getHost(), u.getPort());
|
||||
}
|
||||
}
|
||||
this.url = u;
|
||||
|
||||
}
|
||||
|
||||
public URLImageSource(String href) throws MalformedURLException {
|
||||
this(new URL(null, href));
|
||||
}
|
||||
|
||||
public URLImageSource(URL u, URLConnection uc) {
|
||||
this(u);
|
||||
conn = uc;
|
||||
}
|
||||
|
||||
public URLImageSource(URLConnection uc) {
|
||||
this(uc.getURL(), uc);
|
||||
}
|
||||
|
||||
final boolean checkSecurity(Object context, boolean quiet) {
|
||||
// If actualHost is not null, then the host/port parameters that
|
||||
// the image was actually fetched from were different than the
|
||||
// host/port parameters the original URL specified for at least
|
||||
// one of the download attempts. The original URL security was
|
||||
// checked when the applet got a handle to the image, so we only
|
||||
// need to check for the real host/port.
|
||||
if (actualHost != null) {
|
||||
try {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkConnect(actualHost, actualPort, context);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
if (!quiet) {
|
||||
throw e;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private synchronized URLConnection getConnection() throws IOException {
|
||||
URLConnection c;
|
||||
if (conn != null) {
|
||||
c = conn;
|
||||
conn = null;
|
||||
} else {
|
||||
c = url.openConnection();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
protected ImageDecoder getDecoder() {
|
||||
InputStream is = null;
|
||||
String type = null;
|
||||
URLConnection c = null;
|
||||
try {
|
||||
c = getConnection();
|
||||
is = c.getInputStream();
|
||||
type = c.getContentType();
|
||||
URL u = c.getURL();
|
||||
if (u != url && (!u.getHost().equals(url.getHost()) ||
|
||||
u.getPort() != url.getPort()))
|
||||
{
|
||||
// The image is allowed to come from either the host/port
|
||||
// listed in the original URL, or it can come from one other
|
||||
// host/port that the URL is redirected to. More than that
|
||||
// and we give up and just throw a SecurityException.
|
||||
if (actualHost != null && (!actualHost.equals(u.getHost()) ||
|
||||
actualPort != u.getPort()))
|
||||
{
|
||||
throw new SecurityException("image moved!");
|
||||
}
|
||||
actualHost = u.getHost();
|
||||
actualPort = u.getPort();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e2) {
|
||||
}
|
||||
} else if (c instanceof HttpURLConnection) {
|
||||
((HttpURLConnection)c).disconnect();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageDecoder id = decoderForType(is, type);
|
||||
if (id == null) {
|
||||
id = getDecoder(is);
|
||||
}
|
||||
|
||||
if (id == null) {
|
||||
// probably, no appropriate decoder
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
} else if (c instanceof HttpURLConnection) {
|
||||
((HttpURLConnection)c).disconnect();
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
121
jdkSrc/jdk8/sun/awt/image/VSyncedBSManager.java
Normal file
121
jdkSrc/jdk8/sun/awt/image/VSyncedBSManager.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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.
|
||||
*/
|
||||
|
||||
package sun.awt.image;
|
||||
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Manages v-synced buffer strategies.
|
||||
*/
|
||||
public abstract class VSyncedBSManager {
|
||||
|
||||
private static VSyncedBSManager theInstance;
|
||||
|
||||
private static final boolean vSyncLimit =
|
||||
Boolean.valueOf((String)java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction(
|
||||
"sun.java2d.vsynclimit", "true")));
|
||||
|
||||
private static VSyncedBSManager getInstance(boolean create) {
|
||||
if (theInstance == null && create) {
|
||||
theInstance =
|
||||
vSyncLimit ? new SingleVSyncedBSMgr() : new NoLimitVSyncBSMgr();
|
||||
}
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
abstract boolean checkAllowed(BufferStrategy bs);
|
||||
abstract void relinquishVsync(BufferStrategy bs);
|
||||
|
||||
/**
|
||||
* Returns true if the buffer strategy is allowed to be created
|
||||
* v-synced.
|
||||
*
|
||||
* @return true if the bs is allowed to be v-synced, false otherwise
|
||||
*/
|
||||
public static boolean vsyncAllowed(BufferStrategy bs) {
|
||||
VSyncedBSManager bsm = getInstance(true);
|
||||
return bsm.checkAllowed(bs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets the manager know that this buffer strategy is no longer interested
|
||||
* in being v-synced.
|
||||
*/
|
||||
public static synchronized void releaseVsync(BufferStrategy bs) {
|
||||
VSyncedBSManager bsm = getInstance(false);
|
||||
if (bsm != null) {
|
||||
bsm.relinquishVsync(bs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of the manager which allows any buffer strategy to be
|
||||
* v-synced.
|
||||
*/
|
||||
private static final class NoLimitVSyncBSMgr extends VSyncedBSManager {
|
||||
@Override
|
||||
boolean checkAllowed(BufferStrategy bs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void relinquishVsync(BufferStrategy bs) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of the manager which allows only one buffer strategy to
|
||||
* be v-synced at any give moment in the vm.
|
||||
*/
|
||||
private static final class SingleVSyncedBSMgr extends VSyncedBSManager {
|
||||
private WeakReference<BufferStrategy> strategy;
|
||||
|
||||
@Override
|
||||
public synchronized boolean checkAllowed(BufferStrategy bs) {
|
||||
if (strategy != null) {
|
||||
BufferStrategy current = strategy.get();
|
||||
if (current != null) {
|
||||
return (current == bs);
|
||||
}
|
||||
}
|
||||
strategy = new WeakReference<BufferStrategy>(bs);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void relinquishVsync(BufferStrategy bs) {
|
||||
if (strategy != null) {
|
||||
BufferStrategy b = strategy.get();
|
||||
if (b == bs) {
|
||||
strategy.clear();
|
||||
strategy = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
410
jdkSrc/jdk8/sun/awt/image/VolatileSurfaceManager.java
Normal file
410
jdkSrc/jdk8/sun/awt/image/VolatileSurfaceManager.java
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.VolatileImage;
|
||||
import sun.awt.DisplayChangedListener;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
|
||||
/**
|
||||
* This SurfaceManager variant manages an accelerated volatile surface, if it
|
||||
* is possible to create that surface. If there is limited accelerated
|
||||
* memory, or if the volatile surface disappears due to an operating system
|
||||
* event, the VolatileSurfaceManager will attempt to restore the
|
||||
* accelerated surface. If that fails, a system memory surface will be
|
||||
* created in its place.
|
||||
*/
|
||||
public abstract class VolatileSurfaceManager
|
||||
extends SurfaceManager
|
||||
implements DisplayChangedListener
|
||||
{
|
||||
/**
|
||||
* A reference to the VolatileImage whose contents are being managed.
|
||||
*/
|
||||
protected SunVolatileImage vImg;
|
||||
|
||||
/**
|
||||
* The accelerated SurfaceData object.
|
||||
*/
|
||||
protected SurfaceData sdAccel;
|
||||
|
||||
/**
|
||||
* The software-based SurfaceData object. Only create when first asked
|
||||
* to (otherwise it is a waste of memory as it will only be used in
|
||||
* situations of surface loss).
|
||||
*/
|
||||
protected SurfaceData sdBackup;
|
||||
|
||||
/**
|
||||
* The current SurfaceData object.
|
||||
*/
|
||||
protected SurfaceData sdCurrent;
|
||||
|
||||
/**
|
||||
* A record-keeping object. This keeps track of which SurfaceData was
|
||||
* in use during the last call to validate(). This lets us see whether
|
||||
* the SurfaceData object has changed since then and allows us to return
|
||||
* the correct returnCode to the user in the validate() call.
|
||||
*/
|
||||
protected SurfaceData sdPrevious;
|
||||
|
||||
/**
|
||||
* Tracks loss of surface contents; queriable by user to see whether
|
||||
* contents need to be restored.
|
||||
*/
|
||||
protected boolean lostSurface;
|
||||
|
||||
/**
|
||||
* Context for extra initialization parameters.
|
||||
*/
|
||||
protected Object context;
|
||||
|
||||
protected VolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
this.vImg = vImg;
|
||||
this.context = context;
|
||||
|
||||
GraphicsEnvironment ge =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
// We could have a HeadlessGE at this point, so double-check before
|
||||
// assuming anything.
|
||||
if (ge instanceof SunGraphicsEnvironment) {
|
||||
((SunGraphicsEnvironment)ge).addDisplayChangedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This init function is separate from the constructor because the
|
||||
* things we are doing here necessitate the object's existence.
|
||||
* Otherwise, we end up calling into a subclass' overridden method
|
||||
* during construction, before that subclass is completely constructed.
|
||||
*/
|
||||
public void initialize() {
|
||||
if (isAccelerationEnabled()) {
|
||||
sdAccel = initAcceleratedSurface();
|
||||
if (sdAccel != null) {
|
||||
sdCurrent = sdAccel;
|
||||
}
|
||||
}
|
||||
// only initialize the backup surface for images with unforced
|
||||
// acceleration type
|
||||
if (sdCurrent == null &&
|
||||
vImg.getForcedAccelSurfaceType() == UNDEFINED)
|
||||
{
|
||||
sdCurrent = getBackupSurface();
|
||||
}
|
||||
}
|
||||
|
||||
public SurfaceData getPrimarySurfaceData() {
|
||||
return sdCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if acceleration is enabled. If not, we simply use the
|
||||
* backup SurfaceData object and return quickly from most methods
|
||||
* in this class.
|
||||
*/
|
||||
protected abstract boolean isAccelerationEnabled();
|
||||
|
||||
/**
|
||||
* Get the image ready for rendering. This method is called to make
|
||||
* sure that the accelerated SurfaceData exists and is
|
||||
* ready to be used. Users call this method prior to any set of
|
||||
* rendering to or from the image, to make sure the image is ready
|
||||
* and compatible with the given GraphicsConfiguration.
|
||||
*
|
||||
* The image may not be "ready" if either we had problems creating
|
||||
* it in the first place (e.g., there was no space in vram) or if
|
||||
* the surface became lost (e.g., some other app or the OS caused
|
||||
* vram surfaces to be removed).
|
||||
*
|
||||
* Note that we want to return RESTORED in any situation where the
|
||||
* SurfaceData is different than it was last time. So whether it's
|
||||
* software or hardware, if we have a different SurfaceData object,
|
||||
* then the contents have been altered and we must reflect that
|
||||
* change to the user.
|
||||
*/
|
||||
public int validate(GraphicsConfiguration gc) {
|
||||
int returnCode = VolatileImage.IMAGE_OK;
|
||||
boolean lostSurfaceTmp = lostSurface;
|
||||
lostSurface = false;
|
||||
|
||||
if (isAccelerationEnabled()) {
|
||||
if (!isConfigValid(gc)) {
|
||||
// If we're asked to render to a different device than the
|
||||
// one we were created under, return INCOMPATIBLE error code.
|
||||
// Note that a null gc simply ignores the incompatibility
|
||||
// issue
|
||||
returnCode = VolatileImage.IMAGE_INCOMPATIBLE;
|
||||
} else if (sdAccel == null) {
|
||||
// We either had problems creating the surface or the display
|
||||
// mode changed and we nullified the old one. Try it again.
|
||||
sdAccel = initAcceleratedSurface();
|
||||
if (sdAccel != null) {
|
||||
// set the current SurfaceData to accelerated version
|
||||
sdCurrent = sdAccel;
|
||||
// we don't need the system memory surface anymore, so
|
||||
// let's release it now (it can always be restored later)
|
||||
sdBackup = null;
|
||||
returnCode = VolatileImage.IMAGE_RESTORED;
|
||||
} else {
|
||||
sdCurrent = getBackupSurface();
|
||||
}
|
||||
} else if (sdAccel.isSurfaceLost()) {
|
||||
try {
|
||||
restoreAcceleratedSurface();
|
||||
// set the current SurfaceData to accelerated version
|
||||
sdCurrent = sdAccel;
|
||||
// restoration successful: accel surface no longer lost
|
||||
sdAccel.setSurfaceLost(false);
|
||||
// we don't need the system memory surface anymore, so
|
||||
// let's release it now (it can always be restored later)
|
||||
sdBackup = null;
|
||||
returnCode = VolatileImage.IMAGE_RESTORED;
|
||||
} catch (sun.java2d.InvalidPipeException e) {
|
||||
// Set the current SurfaceData to software version so that
|
||||
// drawing can continue. Note that we still have
|
||||
// the lostAccelSurface flag set so that we will continue
|
||||
// to attempt to restore the accelerated surface.
|
||||
sdCurrent = getBackupSurface();
|
||||
}
|
||||
} else if (lostSurfaceTmp) {
|
||||
// Something else triggered this loss/restoration. Could
|
||||
// be a palette change that didn't require a SurfaceData
|
||||
// recreation but merely a re-rendering of the pixels.
|
||||
returnCode = VolatileImage.IMAGE_RESTORED;
|
||||
}
|
||||
} else if (sdAccel != null) {
|
||||
// if the "acceleration enabled" state changed to disabled,
|
||||
// switch to software surface
|
||||
sdCurrent = getBackupSurface();
|
||||
sdAccel = null;
|
||||
returnCode = VolatileImage.IMAGE_RESTORED;
|
||||
}
|
||||
|
||||
if ((returnCode != VolatileImage.IMAGE_INCOMPATIBLE) &&
|
||||
(sdCurrent != sdPrevious))
|
||||
{
|
||||
// contents have changed - return RESTORED to user
|
||||
sdPrevious = sdCurrent;
|
||||
returnCode = VolatileImage.IMAGE_RESTORED;
|
||||
}
|
||||
|
||||
if (returnCode == VolatileImage.IMAGE_RESTORED) {
|
||||
// clear the current surface with the background color,
|
||||
// only if the surface has been restored
|
||||
initContents();
|
||||
}
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if rendering data was lost since the last validate call.
|
||||
*
|
||||
* @see java.awt.image.VolatileImage#contentsLost
|
||||
*/
|
||||
public boolean contentsLost() {
|
||||
return lostSurface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new accelerated surface that is compatible with the
|
||||
* current GraphicsConfiguration. Returns the new accelerated
|
||||
* SurfaceData object, or null if the surface creation was not successful.
|
||||
*
|
||||
* Platform-specific subclasses should initialize an accelerated
|
||||
* surface (e.g. a DirectDraw surface on Windows, an OpenGL FBO,
|
||||
* or an X11 pixmap).
|
||||
*/
|
||||
protected abstract SurfaceData initAcceleratedSurface();
|
||||
|
||||
/**
|
||||
* Creates a software-based surface (of type BufImgSurfaceData).
|
||||
* The software representation is only created when needed, which
|
||||
* is only during some situation in which the hardware surface
|
||||
* cannot be allocated. This allows apps to at least run,
|
||||
* albeit more slowly than they would otherwise.
|
||||
*/
|
||||
protected SurfaceData getBackupSurface() {
|
||||
if (sdBackup == null) {
|
||||
BufferedImage bImg = vImg.getBackupImage();
|
||||
// Sabotage the acceleration capabilities of the BufImg surface
|
||||
SunWritableRaster.stealTrackable(bImg
|
||||
.getRaster()
|
||||
.getDataBuffer()).setUntrackable();
|
||||
sdBackup = BufImgSurfaceData.createData(bImg);
|
||||
}
|
||||
return sdBackup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set contents of the current SurfaceData to default state (i.e. clear
|
||||
* the background).
|
||||
*/
|
||||
public void initContents() {
|
||||
// images with forced acceleration type may have a null sdCurrent
|
||||
// because we do not create a backup surface for them
|
||||
if (sdCurrent != null) {
|
||||
Graphics g = vImg.createGraphics();
|
||||
g.clearRect(0, 0, vImg.getWidth(), vImg.getHeight());
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from a SurfaceData object, indicating that our
|
||||
* accelerated surface has been lost and should be restored (perhaps
|
||||
* using a backup system memory surface). Returns the newly restored
|
||||
* primary SurfaceData object.
|
||||
*/
|
||||
public SurfaceData restoreContents() {
|
||||
return getBackupSurface();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the accelerated surface is the current SurfaceData for this manager,
|
||||
* sets the variable lostSurface to true, which indicates that something
|
||||
* happened to the image under management. This variable is used in the
|
||||
* validate method to tell the caller that the surface contents need to
|
||||
* be restored.
|
||||
*/
|
||||
public void acceleratedSurfaceLost() {
|
||||
if (isAccelerationEnabled() && (sdCurrent == sdAccel)) {
|
||||
lostSurface = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore sdAccel in case it was lost. Do nothing in this
|
||||
* default case; platform-specific implementations may do more in
|
||||
* this situation as appropriate.
|
||||
*/
|
||||
protected void restoreAcceleratedSurface() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from SunGraphicsEnv when there has been a display mode change.
|
||||
* Note that we simply invalidate hardware surfaces here; we do not
|
||||
* attempt to recreate or re-render them. This is to avoid threading
|
||||
* conflicts with the native toolkit and associated threads. Instead,
|
||||
* we just nullify the old surface data object and wait for a future
|
||||
* method in the rendering process to recreate the surface.
|
||||
*/
|
||||
public void displayChanged() {
|
||||
if (!isAccelerationEnabled()) {
|
||||
return;
|
||||
}
|
||||
lostSurface = true;
|
||||
if (sdAccel != null) {
|
||||
// First, nullify the software surface. This guards against
|
||||
// using a SurfaceData that was created in a different
|
||||
// display mode.
|
||||
sdBackup = null;
|
||||
// Now, invalidate the old hardware-based SurfaceData
|
||||
// Note that getBackupSurface may set sdAccel to null so we have to invalidate it before
|
||||
SurfaceData oldData = sdAccel;
|
||||
sdAccel = null;
|
||||
oldData.invalidate();
|
||||
sdCurrent = getBackupSurface();
|
||||
}
|
||||
// Update graphicsConfig for the vImg in case it changed due to
|
||||
// this display change event
|
||||
vImg.updateGraphicsConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* When device palette changes, need to force a new copy
|
||||
* of the image into our hardware cache to update the
|
||||
* color indices of the pixels (indexed mode only).
|
||||
*/
|
||||
public void paletteChanged() {
|
||||
lostSurface = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by validate() to see whether the GC passed in is ok for
|
||||
* rendering to. This generic implementation checks to see
|
||||
* whether the GC is either null or is from the same
|
||||
* device as the one that this image was created on. Platform-
|
||||
* specific implementations may perform other checks as
|
||||
* appropriate.
|
||||
*/
|
||||
protected boolean isConfigValid(GraphicsConfiguration gc) {
|
||||
return ((gc == null) ||
|
||||
(gc.getDevice() == vImg.getGraphicsConfig().getDevice()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
|
||||
if (isConfigValid(gc)) {
|
||||
return isAccelerationEnabled() ?
|
||||
new AcceleratedImageCapabilities() :
|
||||
new ImageCapabilities(false);
|
||||
}
|
||||
return super.getCapabilities(gc);
|
||||
}
|
||||
|
||||
private class AcceleratedImageCapabilities
|
||||
extends ImageCapabilities
|
||||
{
|
||||
AcceleratedImageCapabilities() {
|
||||
super(false);
|
||||
}
|
||||
@Override
|
||||
public boolean isAccelerated() {
|
||||
return (sdCurrent == sdAccel);
|
||||
}
|
||||
@Override
|
||||
public boolean isTrueVolatile() {
|
||||
return isAccelerated();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any associated hardware memory for this image by
|
||||
* calling flush on sdAccel. This method forces a lostSurface
|
||||
* situation so any future operations on the image will need to
|
||||
* revalidate the image first.
|
||||
*/
|
||||
public void flush() {
|
||||
lostSurface = true;
|
||||
SurfaceData oldSD = sdAccel;
|
||||
sdAccel = null;
|
||||
if (oldSD != null) {
|
||||
oldSD.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
125
jdkSrc/jdk8/sun/awt/image/WritableRasterNative.java
Normal file
125
jdkSrc/jdk8/sun/awt/image/WritableRasterNative.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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 sun.awt.image;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.PixelInterleavedSampleModel;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* WritableRasterNative
|
||||
* This class exists to wrap a native DataBuffer object. The
|
||||
* standard WritableRaster object assumes that a DataBuffer
|
||||
* of a given type (e.g., DataBuffer.TYPE_INT) implies a certain
|
||||
* subclass (e.g., DataBufferInt). But this is not always the
|
||||
* case. DataBufferNative, for example, may allow access to
|
||||
* integer-based data, but it is not DataBufferInt (which is a
|
||||
* final class and cannot be subclassed).
|
||||
* So this class exists simply to allow the WritableRaster
|
||||
* functionality for this new kind of DataBuffer object.
|
||||
*/
|
||||
public class WritableRasterNative extends WritableRaster {
|
||||
|
||||
public static WritableRasterNative createNativeRaster(SampleModel sm,
|
||||
DataBuffer db)
|
||||
{
|
||||
return new WritableRasterNative(sm, db);
|
||||
}
|
||||
|
||||
protected WritableRasterNative(SampleModel sm, DataBuffer db) {
|
||||
super(sm, db, new Point(0, 0));
|
||||
}
|
||||
|
||||
public static WritableRasterNative createNativeRaster(ColorModel cm,
|
||||
SurfaceData sd,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
SampleModel smHw = null;
|
||||
int dataType = 0;
|
||||
int scanStride = width;
|
||||
|
||||
switch (cm.getPixelSize()) {
|
||||
case 8:
|
||||
case 12:
|
||||
// 8-bits uses PixelInterleavedSampleModel
|
||||
if (cm.getPixelSize() == 8) {
|
||||
dataType = DataBuffer.TYPE_BYTE;
|
||||
} else {
|
||||
dataType = DataBuffer.TYPE_USHORT;
|
||||
}
|
||||
int[] bandOffsets = new int[1];
|
||||
bandOffsets[0] = 0;
|
||||
smHw = new PixelInterleavedSampleModel(dataType, width,
|
||||
height,
|
||||
1, scanStride,
|
||||
bandOffsets);
|
||||
break;
|
||||
|
||||
// all others use SinglePixelPackedSampleModel
|
||||
case 15:
|
||||
case 16:
|
||||
dataType = DataBuffer.TYPE_USHORT;
|
||||
int[] bitMasks = new int[3];
|
||||
DirectColorModel dcm = (DirectColorModel)cm;
|
||||
bitMasks[0] = dcm.getRedMask();
|
||||
bitMasks[1] = dcm.getGreenMask();
|
||||
bitMasks[2] = dcm.getBlueMask();
|
||||
smHw = new SinglePixelPackedSampleModel(dataType, width,
|
||||
height, scanStride,
|
||||
bitMasks);
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
dataType = DataBuffer.TYPE_INT;
|
||||
bitMasks = new int[3];
|
||||
dcm = (DirectColorModel)cm;
|
||||
bitMasks[0] = dcm.getRedMask();
|
||||
bitMasks[1] = dcm.getGreenMask();
|
||||
bitMasks[2] = dcm.getBlueMask();
|
||||
smHw = new SinglePixelPackedSampleModel(dataType, width,
|
||||
height, scanStride,
|
||||
bitMasks);
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Unsupported depth " +
|
||||
cm.getPixelSize());
|
||||
}
|
||||
|
||||
DataBuffer dbn = new DataBufferNative(sd, dataType,
|
||||
width, height);
|
||||
return new WritableRasterNative(smHw, dbn);
|
||||
}
|
||||
}
|
||||
178
jdkSrc/jdk8/sun/awt/image/XbmImageDecoder.java
Normal file
178
jdkSrc/jdk8/sun/awt/image/XbmImageDecoder.java
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2003, 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Reads xbitmap format images into a DIBitmap structure.
|
||||
*/
|
||||
package sun.awt.image;
|
||||
|
||||
import java.io.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* Parse files of the form:
|
||||
*
|
||||
* #define foo_width w
|
||||
* #define foo_height h
|
||||
* static char foo_bits[] = {
|
||||
* 0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,
|
||||
* 0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,
|
||||
* 0xnn,0xnn,0xnn,0xnn};
|
||||
*
|
||||
* @author James Gosling
|
||||
*/
|
||||
public class XbmImageDecoder extends ImageDecoder {
|
||||
private static byte XbmColormap[] = {(byte) 255, (byte) 255, (byte) 255,
|
||||
0, 0, 0};
|
||||
private static int XbmHints = (ImageConsumer.TOPDOWNLEFTRIGHT |
|
||||
ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEPASS |
|
||||
ImageConsumer.SINGLEFRAME);
|
||||
|
||||
public XbmImageDecoder(InputStreamImageSource src, InputStream is) {
|
||||
super(src, is);
|
||||
if (!(input instanceof BufferedInputStream)) {
|
||||
// If the topmost stream is a metered stream,
|
||||
// we take forever to decode the image...
|
||||
input = new BufferedInputStream(input, 80);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An error has occurred. Throw an exception.
|
||||
*/
|
||||
private static void error(String s1) throws ImageFormatException {
|
||||
throw new ImageFormatException(s1);
|
||||
}
|
||||
|
||||
/**
|
||||
* produce an image from the stream.
|
||||
*/
|
||||
public void produceImage() throws IOException, ImageFormatException {
|
||||
char nm[] = new char[80];
|
||||
int c;
|
||||
int i = 0;
|
||||
int state = 0;
|
||||
int H = 0;
|
||||
int W = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
boolean start = true;
|
||||
byte raster[] = null;
|
||||
IndexColorModel model = null;
|
||||
while (!aborted && (c = input.read()) != -1) {
|
||||
if ('a' <= c && c <= 'z' ||
|
||||
'A' <= c && c <= 'Z' ||
|
||||
'0' <= c && c <= '9' || c == '#' || c == '_') {
|
||||
if (i < 78)
|
||||
nm[i++] = (char) c;
|
||||
} else if (i > 0) {
|
||||
int nc = i;
|
||||
i = 0;
|
||||
if (start) {
|
||||
if (nc != 7 ||
|
||||
nm[0] != '#' ||
|
||||
nm[1] != 'd' ||
|
||||
nm[2] != 'e' ||
|
||||
nm[3] != 'f' ||
|
||||
nm[4] != 'i' ||
|
||||
nm[5] != 'n' ||
|
||||
nm[6] != 'e')
|
||||
{
|
||||
error("Not an XBM file");
|
||||
}
|
||||
start = false;
|
||||
}
|
||||
if (nm[nc - 1] == 'h')
|
||||
state = 1; /* expecting width */
|
||||
else if (nm[nc - 1] == 't' && nc > 1 && nm[nc - 2] == 'h')
|
||||
state = 2; /* expecting height */
|
||||
else if (nc > 2 && state < 0 && nm[0] == '0' && nm[1] == 'x') {
|
||||
int n = 0;
|
||||
for (int p = 2; p < nc; p++) {
|
||||
c = nm[p];
|
||||
if ('0' <= c && c <= '9')
|
||||
c = c - '0';
|
||||
else if ('A' <= c && c <= 'Z')
|
||||
c = c - 'A' + 10;
|
||||
else if ('a' <= c && c <= 'z')
|
||||
c = c - 'a' + 10;
|
||||
else
|
||||
c = 0;
|
||||
n = n * 16 + c;
|
||||
}
|
||||
for (int mask = 1; mask <= 0x80; mask <<= 1) {
|
||||
if (x < W) {
|
||||
if ((n & mask) != 0)
|
||||
raster[x] = 1;
|
||||
else
|
||||
raster[x] = 0;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
if (x >= W) {
|
||||
if (setPixels(0, y, W, 1, model, raster, 0, W) <= 0) {
|
||||
return;
|
||||
}
|
||||
x = 0;
|
||||
if (y++ >= H) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int n = 0;
|
||||
for (int p = 0; p < nc; p++)
|
||||
if ('0' <= (c = nm[p]) && c <= '9')
|
||||
n = n * 10 + c - '0';
|
||||
else {
|
||||
n = -1;
|
||||
break;
|
||||
}
|
||||
if (n > 0 && state > 0) {
|
||||
if (state == 1)
|
||||
W = n;
|
||||
else
|
||||
H = n;
|
||||
if (W == 0 || H == 0)
|
||||
state = 0;
|
||||
else {
|
||||
model = new IndexColorModel(8, 2, XbmColormap,
|
||||
0, false, 0);
|
||||
setDimensions(W, H);
|
||||
setColorModel(model);
|
||||
setHints(XbmHints);
|
||||
headerComplete();
|
||||
raster = new byte[W];
|
||||
state = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input.close();
|
||||
imageComplete(ImageConsumer.STATICIMAGEDONE, true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user