diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407 (patch) | |
tree | df5a6539447324de36e95b057d6b9f0361b7a250 /awt/java/awt/image/AreaAveragingScaleFilter.java | |
download | frameworks_native-7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407.zip frameworks_native-7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407.tar.gz frameworks_native-7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407.tar.bz2 |
Initial Contribution
Diffstat (limited to 'awt/java/awt/image/AreaAveragingScaleFilter.java')
-rw-r--r-- | awt/java/awt/image/AreaAveragingScaleFilter.java | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/awt/java/awt/image/AreaAveragingScaleFilter.java b/awt/java/awt/image/AreaAveragingScaleFilter.java new file mode 100644 index 0000000..f4933db --- /dev/null +++ b/awt/java/awt/image/AreaAveragingScaleFilter.java @@ -0,0 +1,253 @@ +/* + * 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.Arrays; + + +/** + * The AreaAveragingScaleFilter class scales the source image using + * area averaging algorithm. This algorithm provides a source image + * with a new image containing the resampled image. + */ +public class AreaAveragingScaleFilter extends ReplicateScaleFilter { + + /** The Constant rgbCM. */ + private static final ColorModel rgbCM = ColorModel.getRGBdefault(); + + /** The Constant averagingFlags. */ + private static final int averagingFlags = (ImageConsumer.TOPDOWNLEFTRIGHT | + ImageConsumer.COMPLETESCANLINES); + + /** The reset. */ + private boolean reset = true; // Flag for used superclass filter + + /** The inited. */ + private boolean inited = false; // All data inited + + /** The sum_r. */ + private int sum_r[]; // Array for average Red samples + + /** The sum_g. */ + private int sum_g[]; // Array for average Green samples + + /** The sum_b. */ + private int sum_b[]; // Array for average Blue samples + + /** The sum_a. */ + private int sum_a[]; // Array for average Alpha samples + + /** The buff. */ + private int buff[]; // Stride buffer + + /** The avg factor. */ + private int avgFactor; // Global averaging factor + + /** The cached dy. */ + private int cachedDY; // Cached number of the destination scanline + + /** The cached dv rest. */ + private int cachedDVRest; // Cached value of rest src scanlines for sum + // pixel samples + // Because data if transfering by whole scanlines + // we are caching only Y coordinate values + + /** + * Instantiates a new AreaAveragingScaleFilter object which scales + * a source image with the specified width and height. + * + * @param width the scaled width of the image. + * @param height the scaled height of the image. + */ + public AreaAveragingScaleFilter(int width, int height) { + super(width, height); + } + + @Override + public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) { + if(reset) { + super.setPixels(x, y, w, h, model, pixels, off, scansize); + } else { + setFilteredPixels(x, y, w, h, model, pixels, off, scansize); + } + } + + @Override + public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) { + if(reset) { + super.setPixels(x, y, w, h, model, pixels, off, scansize); + } else { + setFilteredPixels(x, y, w, h, model, pixels, off, scansize); + } + } + + @Override + public void setHints(int hints) { + super.setHints(hints); + reset = ((hints & averagingFlags) != averagingFlags); + } + + /** + * This method implements the Area Averaging Scale filter. + * The description of algorithm is presented in Java API Specification. + * + * Arrays sum_r, sum_g, sum_b, sum_a have length equals width of destination + * image. In each array's element is accumulating pixel's component values, + * proportional to the area which source pixels will occupy in destination + * image. Then that values will divide by Global averaging + * factor (area of the destination image) for receiving + * average values of destination pixels. + * + * @param x - Src pixels X coordinate + * @param y - Src pixels Y coordinate + * @param w - width of the area of Src pixels + * @param h - height of the area of Src pixels + * @param model - Color Model of Src pixels + * @param pixels - array of Src pixels + * @param off - offset into the Src pixels array + * @param scansize - length of scanline in the pixels array + */ + private void setFilteredPixels(int x, int y, int w, int h, ColorModel model, Object pixels, int off, int scansize){ + if(!inited){ + initialize(); + } + + int srcX, srcY, dx, dy; + int svRest, dvRest, shRest, dhRest, vDif, hDif; + + if(y == 0){ + dy = 0; + dvRest = srcHeight; + }else{ + dy = cachedDY; + dvRest = cachedDVRest; + } + + srcY = y; + svRest = destHeight; + + int srcOff = off; + while (srcY < y + h) { + if (svRest < dvRest) { + vDif = svRest; + } else { + vDif = dvRest; + } + + srcX = 0; + dx = 0; + shRest = destWidth; + dhRest = srcWidth; + while (srcX < w) { + if (shRest < dhRest) { + hDif = shRest; + } else { + hDif = dhRest; + } + int avg = hDif * vDif; // calculation of contribution factor + + int rgb, pix; + if (pixels instanceof int[]) { + pix = ((int[]) pixels)[srcOff + srcX]; + } else { + pix = ((byte[]) pixels)[srcOff + srcX] & 0xff; + } + + rgb = model.getRGB(pix); + int a = rgb >>> 24; + int r = (rgb >> 16) & 0xff; + int g = (rgb >> 8) & 0xff; + int b = rgb & 0xff; + + // accumulating pixel's component values + sum_a[dx] += a * avg; + sum_r[dx] += r * avg; + sum_g[dx] += g * avg; + sum_b[dx] += b * avg; + + shRest -= hDif; + dhRest -= hDif; + + if (shRest == 0) { + srcX++; + shRest = destWidth; + } + + if (dhRest == 0) { + dx++; + dhRest = srcWidth; + } + } + + svRest -= vDif; + dvRest -= vDif; + + if (svRest == 0) { + svRest = destHeight; + srcY++; + srcOff += scansize; + } + + if (dvRest == 0) { + // averaging destination pixel's values + for(int i = 0; i < destWidth; i++){ + int a = (sum_a[i] / avgFactor) & 0xff; + int r = (sum_r[i] / avgFactor) & 0xff; + int g = (sum_g[i] / avgFactor) & 0xff; + int b = (sum_b[i] / avgFactor) & 0xff; + int frgb = (a << 24) | (r << 16) | (g << 8) | b; + buff[i] = frgb; + } + consumer.setPixels(0, dy, destWidth, 1, rgbCM, buff, 0, + destWidth); + dy++; + dvRest = srcHeight; + Arrays.fill(sum_a, 0); + Arrays.fill(sum_r, 0); + Arrays.fill(sum_g, 0); + Arrays.fill(sum_b, 0); + } + + } + + cachedDY = dy; + cachedDVRest = dvRest; + + } + + /** + * Initialization of the auxiliary data. + */ + private void initialize(){ + + sum_a = new int[destWidth]; + sum_r = new int[destWidth]; + sum_g = new int[destWidth]; + sum_b = new int[destWidth]; + + buff = new int[destWidth]; + outpixbuf = buff; + avgFactor = srcWidth * srcHeight; + + inited = true; + } +} + |