diff options
Diffstat (limited to 'awt/java/awt/image/PixelGrabber.java')
-rw-r--r-- | awt/java/awt/image/PixelGrabber.java | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/awt/java/awt/image/PixelGrabber.java b/awt/java/awt/image/PixelGrabber.java new file mode 100644 index 0000000..cecd5c8 --- /dev/null +++ b/awt/java/awt/image/PixelGrabber.java @@ -0,0 +1,408 @@ +/* + * 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; + } + +} |