409 lines
11 KiB
Java
409 lines
11 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/**
|
|
* @author Igor V. Stolyarov
|
|
* @version $Revision$
|
|
*/
|
|
package java.awt.image;
|
|
|
|
import java.awt.Image;
|
|
import java.util.Hashtable;
|
|
|
|
import org.apache.harmony.awt.internal.nls.Messages;
|
|
|
|
public class PixelGrabber implements ImageConsumer {
|
|
|
|
int width;
|
|
int height;
|
|
int X;
|
|
int Y;
|
|
int offset;
|
|
int scanline;
|
|
ImageProducer producer;
|
|
|
|
byte bData[];
|
|
int iData[];
|
|
ColorModel cm;
|
|
|
|
private int grabberStatus;
|
|
private int dataType;
|
|
private boolean isGrabbing;
|
|
private boolean isRGB;
|
|
|
|
|
|
private static final int DATA_TYPE_BYTE = 0;
|
|
private static final int DATA_TYPE_INT = 1;
|
|
private static final int DATA_TYPE_UNDEFINED = 2;
|
|
|
|
private static final int ALL_BITS = (ImageObserver.FRAMEBITS |
|
|
ImageObserver.ALLBITS);
|
|
|
|
private static final int GRABBING_STOP = ALL_BITS | ImageObserver.ERROR;
|
|
|
|
|
|
|
|
public PixelGrabber(ImageProducer ip, int x, int y, int w, int h, int[] pix,
|
|
int off, int scansize) {
|
|
initialize(ip, x, y, w, h, pix, off, scansize, true);
|
|
}
|
|
|
|
public PixelGrabber(Image img, int x, int y, int w, int h, int[] pix,
|
|
int off, int scansize) {
|
|
initialize(img.getSource(), x, y, w, h, pix, off, scansize, true);
|
|
}
|
|
|
|
public PixelGrabber(Image img, int x, int y, int w, int h, boolean forceRGB) {
|
|
initialize(img.getSource(), x, y, w, h, null, 0, 0, forceRGB);
|
|
}
|
|
|
|
public void setProperties(Hashtable<?, ?> props) {
|
|
return;
|
|
}
|
|
|
|
public synchronized Object getPixels() {
|
|
switch(dataType){
|
|
case DATA_TYPE_BYTE:
|
|
return bData;
|
|
case DATA_TYPE_INT:
|
|
return iData;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void setColorModel(ColorModel model) {
|
|
return;
|
|
}
|
|
|
|
public void setPixels(int srcX, int srcY, int srcW, int srcH,
|
|
ColorModel model, byte[] pixels, int srcOff, int srcScan) {
|
|
if(srcY < Y){
|
|
int delta = Y - srcY;
|
|
if(delta >= height) {
|
|
return;
|
|
}
|
|
srcY += delta;
|
|
srcH -= delta;
|
|
srcOff += srcScan * delta;
|
|
}
|
|
|
|
if(srcY + srcH > Y + height){
|
|
srcH = Y + height - srcY;
|
|
if(srcH <= 0) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(srcX < X){
|
|
int delta = X - srcX;
|
|
if(delta >= width) {
|
|
return;
|
|
}
|
|
srcW -= delta;
|
|
srcX += delta;
|
|
srcOff += delta;
|
|
}
|
|
|
|
if(srcX + srcW > X + width){
|
|
srcW = X + width - srcX;
|
|
if(srcW <= 0) {
|
|
return;
|
|
}
|
|
}
|
|
if(scanline == 0) {
|
|
scanline = width;
|
|
}
|
|
int realOff = offset + (srcY - Y) * scanline + (srcX - X);
|
|
switch(dataType){
|
|
case DATA_TYPE_UNDEFINED:
|
|
cm = model;
|
|
if(model != ColorModel.getRGBdefault()){
|
|
bData = new byte[width * height];
|
|
isRGB = false;
|
|
dataType = DATA_TYPE_BYTE;
|
|
}else{
|
|
iData = new int[width * height];
|
|
isRGB = true;
|
|
dataType = DATA_TYPE_INT;
|
|
}
|
|
case DATA_TYPE_BYTE:
|
|
if(!isRGB && cm == model){
|
|
for(int y = 0; y < srcH; y++){
|
|
System.arraycopy(pixels, srcOff, bData, realOff, srcW);
|
|
srcOff += srcScan;
|
|
realOff += scanline;
|
|
}
|
|
break;
|
|
}
|
|
forceToRGB();
|
|
case DATA_TYPE_INT:
|
|
for(int y = 0; y < srcH; y++){
|
|
for(int x = 0; x < srcW; x++){
|
|
iData[realOff + x] = cm.getRGB(pixels[srcOff + x] & 0xff);
|
|
}
|
|
srcOff += srcScan;
|
|
realOff += scanline;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
public void setPixels(int srcX, int srcY, int srcW, int srcH,
|
|
ColorModel model, int[] pixels, int srcOff, int srcScan) {
|
|
|
|
if(srcY < Y){
|
|
int delta = Y - srcY;
|
|
if(delta >= height) {
|
|
return;
|
|
}
|
|
srcY += delta;
|
|
srcH -= delta;
|
|
srcOff += srcScan * delta;
|
|
}
|
|
|
|
if(srcY + srcH > Y + height){
|
|
srcH = Y + height - srcY;
|
|
if(srcH <= 0) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(srcX < X){
|
|
int delta = X - srcX;
|
|
if(delta >= width) {
|
|
return;
|
|
}
|
|
srcW -= delta;
|
|
srcX += delta;
|
|
srcOff += delta;
|
|
}
|
|
|
|
if(srcX + srcW > X + width){
|
|
srcW = X + width - srcX;
|
|
if(srcW <= 0) {
|
|
return;
|
|
}
|
|
}
|
|
if(scanline == 0) {
|
|
scanline = width;
|
|
}
|
|
int realOff = offset + (srcY - Y) * scanline + (srcX - X);
|
|
|
|
int mask = 0xFF;
|
|
|
|
switch(dataType){
|
|
case DATA_TYPE_UNDEFINED:
|
|
cm = model;
|
|
iData = new int[width * height];
|
|
dataType = DATA_TYPE_INT;
|
|
isRGB = (cm == ColorModel.getRGBdefault());
|
|
|
|
case DATA_TYPE_INT:
|
|
if(cm == model){
|
|
for(int y = 0; y < srcH; y++){
|
|
System.arraycopy(pixels, srcOff, iData, realOff, srcW);
|
|
srcOff += srcScan;
|
|
realOff += scanline;
|
|
}
|
|
break;
|
|
}
|
|
mask = 0xFFFFFFFF;
|
|
|
|
case DATA_TYPE_BYTE:
|
|
forceToRGB();
|
|
for(int y = 0; y < srcH; y++){
|
|
for(int x = 0; x < srcW; x++){
|
|
iData[realOff+x] = cm.getRGB(pixels[srcOff+x] & mask);
|
|
}
|
|
srcOff += srcScan;
|
|
realOff += scanline;
|
|
}
|
|
}
|
|
}
|
|
|
|
public synchronized ColorModel getColorModel() {
|
|
return cm;
|
|
}
|
|
|
|
public synchronized boolean grabPixels(long ms)
|
|
throws InterruptedException {
|
|
if((grabberStatus & GRABBING_STOP) != 0){
|
|
return ((grabberStatus & ALL_BITS) != 0);
|
|
}
|
|
|
|
long start = System.currentTimeMillis();
|
|
|
|
if(!isGrabbing){
|
|
isGrabbing = true;
|
|
grabberStatus &= ~ImageObserver.ABORT;
|
|
producer.startProduction(this);
|
|
}
|
|
while((grabberStatus & GRABBING_STOP) == 0){
|
|
if(ms != 0){
|
|
ms = start + ms - System.currentTimeMillis();
|
|
if(ms <= 0) {
|
|
break;
|
|
}
|
|
}
|
|
wait(ms);
|
|
}
|
|
|
|
return ((grabberStatus & ALL_BITS) != 0);
|
|
}
|
|
|
|
public void setDimensions(int w, int h) {
|
|
if(width < 0) {
|
|
width = w - X;
|
|
}
|
|
if(height < 0) {
|
|
height = h - Y;
|
|
}
|
|
|
|
grabberStatus |= ImageObserver.WIDTH | ImageObserver.HEIGHT;
|
|
|
|
if(width <=0 || height <=0){
|
|
imageComplete(STATICIMAGEDONE);
|
|
return;
|
|
}
|
|
|
|
if(isRGB && dataType == DATA_TYPE_UNDEFINED){
|
|
iData = new int[width * height];
|
|
dataType = DATA_TYPE_INT;
|
|
scanline = width;
|
|
}
|
|
}
|
|
|
|
public void setHints(int hints) {
|
|
return;
|
|
}
|
|
|
|
public synchronized void imageComplete(int status) {
|
|
switch(status){
|
|
case IMAGEABORTED:
|
|
grabberStatus |= ImageObserver.ABORT;
|
|
break;
|
|
case IMAGEERROR:
|
|
grabberStatus |= ImageObserver.ERROR | ImageObserver.ABORT;
|
|
break;
|
|
case SINGLEFRAMEDONE:
|
|
grabberStatus |= ImageObserver.FRAMEBITS;
|
|
break;
|
|
case STATICIMAGEDONE:
|
|
grabberStatus |= ImageObserver.ALLBITS;
|
|
break;
|
|
default:
|
|
// awt.26A=Incorrect ImageConsumer completion status
|
|
throw new IllegalArgumentException(Messages.getString("awt.26A")); //$NON-NLS-1$
|
|
}
|
|
isGrabbing = false;
|
|
producer.removeConsumer(this);
|
|
notifyAll();
|
|
}
|
|
|
|
public boolean grabPixels() throws InterruptedException {
|
|
return grabPixels(0);
|
|
}
|
|
|
|
public synchronized void startGrabbing() {
|
|
if((grabberStatus & GRABBING_STOP) != 0){
|
|
return;
|
|
}
|
|
if(!isGrabbing){
|
|
isGrabbing = true;
|
|
grabberStatus &= ~ImageObserver.ABORT;
|
|
producer.startProduction(this);
|
|
}
|
|
}
|
|
|
|
public synchronized void abortGrabbing() {
|
|
imageComplete(IMAGEABORTED);
|
|
}
|
|
|
|
public synchronized int status() {
|
|
return grabberStatus;
|
|
}
|
|
|
|
public synchronized int getWidth() {
|
|
if(width < 0) {
|
|
return -1;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
public synchronized int getStatus() {
|
|
return grabberStatus;
|
|
}
|
|
|
|
public synchronized int getHeight() {
|
|
if(height < 0) {
|
|
return -1;
|
|
}
|
|
return height;
|
|
}
|
|
|
|
private void initialize(ImageProducer ip, int x, int y, int w, int h,
|
|
int pixels[], int off, int scansize, boolean forceRGB){
|
|
|
|
producer = ip;
|
|
X = x;
|
|
Y = y;
|
|
width = w;
|
|
height = h;
|
|
iData = pixels;
|
|
dataType = (pixels == null) ? DATA_TYPE_UNDEFINED : DATA_TYPE_INT;
|
|
offset = off;
|
|
scanline = scansize;
|
|
if(forceRGB){
|
|
cm = ColorModel.getRGBdefault();
|
|
isRGB = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Force pixels to INT RGB mode
|
|
*/
|
|
private void forceToRGB(){
|
|
if (isRGB)
|
|
return;
|
|
|
|
switch(dataType){
|
|
case DATA_TYPE_BYTE:
|
|
iData = new int[width * height];
|
|
for(int i = 0; i < iData.length; i++){
|
|
iData[i] = cm.getRGB(bData[i] & 0xff);
|
|
}
|
|
dataType = DATA_TYPE_INT;
|
|
bData = null;
|
|
break;
|
|
|
|
case DATA_TYPE_INT:
|
|
int buff[] = new int[width * height];
|
|
for(int i = 0; i < iData.length; i++){
|
|
buff[i] = cm.getRGB(iData[i]);
|
|
}
|
|
iData = buff;
|
|
break;
|
|
}
|
|
offset = 0;
|
|
scanline = width;
|
|
cm = ColorModel.getRGBdefault();
|
|
isRGB = true;
|
|
}
|
|
|
|
}
|