blob: 7e8e2dbc795a696a44045f1cc2829e25e7e5f9aa [file] [log] [blame]
/*
* 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.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);
} catch (NullPointerException e) {
if (theConsumer != null) {
theConsumer.imageComplete(ImageConsumer.IMAGEERROR);
}
}
}
}