blob: 51c0f4994200bb365634c2178debbc29b34ee1bd [file] [log] [blame]
/*
* 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.util.Hashtable;
import org.apache.harmony.awt.internal.nls.Messages;
/**
* The ReplicateScaleFilter class scales an source image by replicating rows and
* columns of pixels to scale up or omitting rows and columns of pixels to scale
* down.
*
* @since Android 1.0
*/
public class ReplicateScaleFilter extends ImageFilter {
/**
* The width of a source image.
*/
protected int srcWidth;
/**
* The height of a source image.
*/
protected int srcHeight;
/**
* The width of a destination image.
*/
protected int destWidth;
/**
* The height of a destination image.
*/
protected int destHeight;
/**
* The integer array of source rows.
*/
protected int[] srcrows;
/**
* The integer array of source columns.
*/
protected int[] srccols;
/**
* An Object (byte array with a destination width) provides a row of pixel
* data to the ImageConsumer.
*/
protected Object outpixbuf;
/**
* Instantiates a new ReplicateScaleFilter that filters the image with the
* specified width and height.
*
* @param width
* the width of scaled image.
* @param height
* the height of scaled image.
*/
public ReplicateScaleFilter(int width, int height) {
if (width == 0 || height == 0) {
// awt.234=Width or Height equals zero
throw new IllegalArgumentException(Messages.getString("awt.234")); //$NON-NLS-1$
}
this.destWidth = width;
this.destHeight = height;
}
@SuppressWarnings("unchecked")
@Override
public void setProperties(Hashtable<?, ?> props) {
Hashtable<Object, Object> fprops;
if (props == null) {
fprops = new Hashtable<Object, Object>();
} else {
fprops = (Hashtable<Object, Object>)props.clone();
}
String propName = "Rescale Filters"; //$NON-NLS-1$
String prop = "destWidth=" + destWidth + "; " + //$NON-NLS-1$ //$NON-NLS-2$
"destHeight=" + destHeight; //$NON-NLS-1$
Object o = fprops.get(propName);
if (o != null) {
if (o instanceof String) {
prop = (String)o + "; " + prop; //$NON-NLS-1$
} else {
prop = o.toString() + "; " + prop; //$NON-NLS-1$
}
}
fprops.put(propName, prop);
consumer.setProperties(fprops);
}
// setPixels methods produce pixels according to Java API Spacification
@Override
public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off,
int scansize) {
if (srccols == null) {
initArrays();
}
int buff[];
if (outpixbuf == null || !(outpixbuf instanceof int[])) {
buff = new int[destWidth];
outpixbuf = buff;
} else {
buff = (int[])outpixbuf;
}
int wa = (srcWidth - 1) >>> 1;
int ha = (srcHeight - 1) >>> 1;
int dstX = (x * destWidth + wa) / srcWidth;
int dstY = (y * destHeight + ha) / srcHeight;
int sx, sy, dx, dy;
dy = dstY;
while ((dy < destHeight) && ((sy = srcrows[dy]) < y + h)) {
dx = dstX;
int srcOff = off + (sy - y) * scansize;
while ((dx < destWidth) && ((sx = srccols[dx]) < x + w)) {
buff[dx] = pixels[srcOff + (sx - x)];
dx++;
}
consumer.setPixels(dstX, dy, dx - dstX, 1, model, buff, dstX, destWidth);
dy++;
}
}
@Override
public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off,
int scansize) {
if (srccols == null) {
initArrays();
}
byte buff[];
if (outpixbuf == null || !(outpixbuf instanceof byte[])) {
buff = new byte[destWidth];
outpixbuf = buff;
} else {
buff = (byte[])outpixbuf;
}
int wa = (srcWidth - 1) >>> 1;
int ha = (srcHeight - 1) >>> 1;
int dstX = (x * destWidth + wa) / srcWidth;
int dstY = (y * destHeight + ha) / srcHeight;
int sx, sy, dx, dy;
dy = dstY;
while ((dy < destHeight) && ((sy = srcrows[dy]) < y + h)) {
dx = dstX;
int srcOff = off + (sy - y) * scansize;
while ((dx < destWidth) && ((sx = srccols[dx]) < x + w)) {
buff[dx] = pixels[srcOff + (sx - x)];
dx++;
}
consumer.setPixels(dstX, dy, dx - dstX, 1, model, buff, dstX, destWidth);
dy++;
}
}
@Override
public void setDimensions(int w, int h) {
srcWidth = w;
srcHeight = h;
if (destWidth < 0 && destHeight < 0) {
destWidth = srcWidth;
destHeight = srcHeight;
} else if (destWidth < 0) {
destWidth = destHeight * srcWidth / srcHeight;
} else if (destHeight < 0) {
destHeight = destWidth * srcHeight / srcWidth;
}
consumer.setDimensions(destWidth, destHeight);
}
/**
* Initialization of srccols and srcrows arrays.
*/
private void initArrays() {
if ((destWidth < 0) || (destHeight < 0)) {
throw new IndexOutOfBoundsException();
}
srccols = new int[destWidth];
int ca = srcWidth >>> 1;
for (int i = 0; i < destWidth; i++) {
srccols[i] = (i * srcWidth + ca) / destWidth;
}
srcrows = new int[destHeight];
int ra = srcHeight >>> 1;
for (int i = 0; i < destHeight; i++) {
srcrows[i] = (i * srcHeight + ra) / destHeight;
}
}
}