001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: /**
020: * @author Oleg V. Khaschansky
021: * @version $Revision$
022: */package java.awt.image;
023:
024: import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
025: import org.apache.harmony.awt.internal.nls.Messages;
026:
027: public class BufferedImageFilter extends ImageFilter implements
028: Cloneable {
029: private static final AwtImageBackdoorAccessor accessor = AwtImageBackdoorAccessor
030: .getInstance();
031:
032: private BufferedImageOp op;
033:
034: private WritableRaster raster;
035:
036: private int iData[];
037: private byte bData[];
038:
039: private int width;
040: private int height;
041:
042: private ColorModel cm;
043:
044: private boolean forcedRGB = false;
045: private int transferType = DataBuffer.TYPE_UNDEFINED;
046:
047: public BufferedImageFilter(BufferedImageOp op) {
048: if (op == null) {
049: throw new NullPointerException(Messages.getString("awt.05")); //$NON-NLS-1$
050: }
051: this .op = op;
052: }
053:
054: public BufferedImageOp getBufferedImageOp() {
055: return op;
056: }
057:
058: @Override
059: public void setDimensions(int width, int height) {
060: this .width = width;
061: this .height = height;
062: // Stop image consuming if no pixels expected.
063: if (width <= 0 || height <= 0) {
064: consumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
065: reset();
066: }
067: }
068:
069: @Override
070: public void setColorModel(ColorModel model) {
071: if (this .cm != null && this .cm != model && raster != null) {
072: forceRGB();
073: } else {
074: this .cm = model;
075: }
076: }
077:
078: @Override
079: public void setPixels(int x, int y, int w, int h, ColorModel model,
080: byte[] pixels, int off, int scansize) {
081: setPixels(x, y, w, h, model, pixels, off, scansize, true);
082: }
083:
084: @Override
085: public void setPixels(int x, int y, int w, int h, ColorModel model,
086: int[] pixels, int off, int scansize) {
087: setPixels(x, y, w, h, model, pixels, off, scansize, false);
088: }
089:
090: @Override
091: public void imageComplete(int status) {
092: if (status == STATICIMAGEDONE || status == SINGLEFRAMEDONE) {
093: BufferedImage bim = new BufferedImage(cm, raster,
094: cm.isAlphaPremultiplied, null);
095: bim = op.filter(bim, null);
096: DataBuffer dstDb = bim.getRaster().getDataBuffer();
097: ColorModel dstCm = bim.getColorModel();
098: int dstW = bim.getWidth();
099: int dstH = bim.getHeight();
100:
101: consumer.setDimensions(dstW, dstH);
102:
103: if (dstDb.getDataType() == DataBuffer.TYPE_INT) {
104: consumer.setColorModel(dstCm);
105: consumer.setPixels(0, 0, dstW, dstH, dstCm, accessor
106: .getDataInt(dstDb), 0, dstW);
107: } else if (dstDb.getDataType() == DataBuffer.TYPE_BYTE) {
108: consumer.setColorModel(dstCm);
109: consumer.setPixels(0, 0, dstW, dstH, dstCm, accessor
110: .getDataByte(dstDb), 0, dstW);
111: } else {
112: int dstData[] = bim.getRGB(0, 0, dstW, dstH, null, 0,
113: dstW);
114: dstCm = ColorModel.getRGBdefault();
115: consumer.setColorModel(dstCm);
116: consumer.setPixels(0, 0, dstW, dstH, dstCm, dstData, 0,
117: dstW);
118: }
119: } else if (status == IMAGEERROR || status == IMAGEABORTED) {
120: reset();
121: }
122:
123: consumer.imageComplete(status);
124: }
125:
126: private void setPixels(int x, int y, int w, int h,
127: ColorModel model, Object pixels, int off, int scansize,
128: boolean isByteData) {
129: // Check bounds
130: // Need to copy only the pixels that will fit into the destination area
131: if (x < 0) {
132: w -= x;
133: off += x;
134: x = 0;
135: }
136:
137: if (y < 0) {
138: h -= y;
139: off += y * scansize;
140: y = 0;
141: }
142:
143: if (x + w > width) {
144: w = width - x;
145: }
146:
147: if (y + h > height) {
148: h = height - y;
149: }
150:
151: if (w <= 0 || h <= 0) {
152: return;
153: }
154:
155: // Check model
156: if (this .cm == null) {
157: setColorModel(model);
158: } else if (model == null) {
159: model = this .cm;
160: } else if (!model.equals(this .cm)) {
161: forceRGB();
162: }
163:
164: boolean canArraycopy;
165: // Process pixels
166: switch (transferType) {
167: case DataBuffer.TYPE_UNDEFINED: {
168: if (isByteData) {
169: transferType = DataBuffer.TYPE_BYTE;
170: createRaster(transferType);
171: //bData = new byte[width*height];
172: canArraycopy = !forcedRGB;
173: break;
174: }
175: transferType = DataBuffer.TYPE_INT;
176: createRaster(transferType);
177: //iData = new int[width*height];
178: canArraycopy = !forcedRGB
179: || model.equals(ColorModel.getRGBdefault());
180: break;
181: } // And proceed to copy the pixels
182: case DataBuffer.TYPE_INT: {
183: if (isByteData) { // There are int data already but the new data are bytes
184: forceRGB();
185: canArraycopy = false;
186: break;
187: } else if (!forcedRGB
188: || model.equals(ColorModel.getRGBdefault())) {
189: canArraycopy = true;
190: break;
191: } // Else fallback to the RGB conversion
192: }
193: case DataBuffer.TYPE_BYTE: {
194: if (isByteData && !forcedRGB) {
195: canArraycopy = true;
196: break;
197: }
198:
199: // RGB conversion
200: canArraycopy = false;
201: break;
202: }
203: default: {
204: throw new IllegalStateException(Messages
205: .getString("awt.06")); //$NON-NLS-1$
206: }
207: }
208:
209: off += x;
210: int maxOffset = off + h * scansize;
211: int dstOffset = x + y * width;
212:
213: if (canArraycopy) {
214: Object dstArray = isByteData ? (Object) bData
215: : (Object) iData;
216: for (; off < maxOffset; off += scansize, dstOffset += width) {
217: System.arraycopy(pixels, off, dstArray, dstOffset, w);
218: }
219: } else {
220: // RGB conversion
221: for (; off < maxOffset; off += scansize, dstOffset += width) {
222: int srcPos = off;
223: int dstPos = dstOffset;
224: int maxDstPos = dstOffset + w;
225: for (; dstPos < maxDstPos; dstPos++, srcPos++) {
226: iData[dstPos] = model
227: .getRGB(isByteData ? ((byte[]) pixels)[srcPos]
228: : ((int[]) pixels)[srcPos]);
229: }
230: }
231: }
232: }
233:
234: private void forceRGB() {
235: if (!forcedRGB) {
236: forcedRGB = true;
237: int size = width * height;
238: int rgbData[] = new int[size];
239:
240: if (bData != null) {
241: for (int i = 0; i < size; i++) {
242: rgbData[i] = cm.getRGB(bData[i]);
243: }
244: } else if (iData != null) {
245: for (int i = 0; i < size; i++) {
246: rgbData[i] = cm.getRGB(iData[i]);
247: }
248: }
249:
250: cm = ColorModel.getRGBdefault();
251: DataBufferInt db = new DataBufferInt(rgbData, size);
252: int masks[] = new int[] { 0x00ff0000, 0x0000ff00,
253: 0x000000ff, 0xff000000 };
254: raster = Raster.createPackedRaster(db, width, height,
255: width, masks, null);
256: iData = accessor.getDataInt(db);
257: bData = null;
258: transferType = DataBuffer.TYPE_INT;
259: }
260: }
261:
262: private void reset() {
263: width = 0;
264: height = 0;
265: forcedRGB = false;
266: cm = null;
267: iData = null;
268: bData = null;
269: transferType = DataBuffer.TYPE_UNDEFINED;
270: raster = null;
271: }
272:
273: private void createRaster(int dataType) {
274: boolean createdValidBuffer = false;
275: try {
276: raster = cm.createCompatibleWritableRaster(width, height);
277: int rasterType = raster.getDataBuffer().getDataType();
278: if (rasterType == dataType) {
279: switch (rasterType) {
280: case DataBuffer.TYPE_INT: {
281: iData = accessor.getDataInt(raster.getDataBuffer());
282: if (iData != null) {
283: createdValidBuffer = true;
284: }
285: break;
286: }
287: case DataBuffer.TYPE_BYTE: {
288: bData = accessor
289: .getDataByte(raster.getDataBuffer());
290: if (bData != null) {
291: createdValidBuffer = true;
292: }
293: break;
294: }
295: default:
296: createdValidBuffer = false;
297: }
298:
299: if (cm == ColorModel.getRGBdefault()) {
300: forcedRGB = true;
301: }
302: } else {
303: createdValidBuffer = false;
304: }
305: } catch (Exception e) {
306: createdValidBuffer = false;
307: }
308:
309: if (createdValidBuffer == false) {
310: cm = ColorModel.getRGBdefault();
311: raster = cm.createCompatibleWritableRaster(width, height);
312: iData = accessor.getDataInt(raster.getDataBuffer());
313: bData = null;
314: forcedRGB = true;
315: }
316: }
317: }
|