001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Igor V. Stolyarov
019: * @version $Revision$
020: */package java.awt.image;
021:
022: import java.awt.Image;
023: import java.util.Hashtable;
024:
025: import org.apache.harmony.awt.internal.nls.Messages;
026:
027: public class PixelGrabber implements ImageConsumer {
028:
029: int width;
030: int height;
031: int X;
032: int Y;
033: int offset;
034: int scanline;
035: ImageProducer producer;
036:
037: byte bData[];
038: int iData[];
039: ColorModel cm;
040:
041: private int grabberStatus;
042: private int dataType;
043: private boolean isGrabbing;
044: private boolean isRGB;
045:
046: private static final int DATA_TYPE_BYTE = 0;
047: private static final int DATA_TYPE_INT = 1;
048: private static final int DATA_TYPE_UNDEFINED = 2;
049:
050: private static final int ALL_BITS = (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS);
051:
052: private static final int GRABBING_STOP = ALL_BITS
053: | ImageObserver.ERROR;
054:
055: public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
056: int[] pix, int off, int scansize) {
057: initialize(ip, x, y, w, h, pix, off, scansize, true);
058: }
059:
060: public PixelGrabber(Image img, int x, int y, int w, int h,
061: int[] pix, int off, int scansize) {
062: initialize(img.getSource(), x, y, w, h, pix, off, scansize,
063: true);
064: }
065:
066: public PixelGrabber(Image img, int x, int y, int w, int h,
067: boolean forceRGB) {
068: initialize(img.getSource(), x, y, w, h, null, 0, 0, forceRGB);
069: }
070:
071: public void setProperties(Hashtable<?, ?> props) {
072: return;
073: }
074:
075: public synchronized Object getPixels() {
076: switch (dataType) {
077: case DATA_TYPE_BYTE:
078: return bData;
079: case DATA_TYPE_INT:
080: return iData;
081: default:
082: return null;
083: }
084: }
085:
086: public void setColorModel(ColorModel model) {
087: return;
088: }
089:
090: public void setPixels(int srcX, int srcY, int srcW, int srcH,
091: ColorModel model, byte[] pixels, int srcOff, int srcScan) {
092: if (srcY < Y) {
093: int delta = Y - srcY;
094: if (delta >= height) {
095: return;
096: }
097: srcY += delta;
098: srcH -= delta;
099: srcOff += srcScan * delta;
100: }
101:
102: if (srcY + srcH > Y + height) {
103: srcH = Y + height - srcY;
104: if (srcH <= 0) {
105: return;
106: }
107: }
108:
109: if (srcX < X) {
110: int delta = X - srcX;
111: if (delta >= width) {
112: return;
113: }
114: srcW -= delta;
115: srcX += delta;
116: srcOff += delta;
117: }
118:
119: if (srcX + srcW > X + width) {
120: srcW = X + width - srcX;
121: if (srcW <= 0) {
122: return;
123: }
124: }
125: if (scanline == 0) {
126: scanline = width;
127: }
128: int realOff = offset + (srcY - Y) * scanline + (srcX - X);
129: switch (dataType) {
130: case DATA_TYPE_UNDEFINED:
131: cm = model;
132: if (model != ColorModel.getRGBdefault()) {
133: bData = new byte[width * height];
134: isRGB = false;
135: dataType = DATA_TYPE_BYTE;
136: } else {
137: iData = new int[width * height];
138: isRGB = true;
139: dataType = DATA_TYPE_INT;
140: }
141: case DATA_TYPE_BYTE:
142: if (!isRGB && cm == model) {
143: for (int y = 0; y < srcH; y++) {
144: System.arraycopy(pixels, srcOff, bData, realOff,
145: srcW);
146: srcOff += srcScan;
147: realOff += scanline;
148: }
149: break;
150: }
151: forceToRGB();
152: case DATA_TYPE_INT:
153: for (int y = 0; y < srcH; y++) {
154: for (int x = 0; x < srcW; x++) {
155: iData[realOff++] = cm
156: .getRGB(pixels[srcOff++] & 0xff);
157: }
158: srcOff += srcScan;
159: realOff += scanline;
160: }
161: }
162:
163: return;
164: }
165:
166: public void setPixels(int srcX, int srcY, int srcW, int srcH,
167: ColorModel model, int[] pixels, int srcOff, int srcScan) {
168:
169: if (srcY < Y) {
170: int delta = Y - srcY;
171: if (delta >= height) {
172: return;
173: }
174: srcY += delta;
175: srcH -= delta;
176: srcOff += srcScan * delta;
177: }
178:
179: if (srcY + srcH > Y + height) {
180: srcH = Y + height - srcY;
181: if (srcH <= 0) {
182: return;
183: }
184: }
185:
186: if (srcX < X) {
187: int delta = X - srcX;
188: if (delta >= width) {
189: return;
190: }
191: srcW -= delta;
192: srcX += delta;
193: srcOff += delta;
194: }
195:
196: if (srcX + srcW > X + width) {
197: srcW = X + width - srcX;
198: if (srcW <= 0) {
199: return;
200: }
201: }
202: if (scanline == 0) {
203: scanline = width;
204: }
205: int realOff = offset + (srcY - Y) * scanline + (srcX - X);
206:
207: int mask = 0xFF;
208:
209: switch (dataType) {
210: case DATA_TYPE_UNDEFINED:
211: cm = model;
212: iData = new int[width * height];
213: dataType = DATA_TYPE_INT;
214: isRGB = (cm == ColorModel.getRGBdefault());
215:
216: case DATA_TYPE_INT:
217: if (cm == model) {
218: for (int y = 0; y < srcH; y++) {
219: System.arraycopy(pixels, srcOff, iData, realOff,
220: srcW);
221: srcOff += srcScan;
222: realOff += scanline;
223: }
224: break;
225: }
226: mask = 0xFFFFFFFF;
227:
228: case DATA_TYPE_BYTE:
229: forceToRGB();
230: for (int y = 0; y < srcH; y++) {
231: for (int x = 0; x < srcW; x++) {
232: iData[realOff + x] = cm.getRGB(pixels[srcOff + x]
233: & mask);
234: }
235: srcOff += srcScan;
236: realOff += scanline;
237: }
238: }
239: }
240:
241: public synchronized ColorModel getColorModel() {
242: return cm;
243: }
244:
245: public synchronized boolean grabPixels(long ms)
246: throws InterruptedException {
247: if ((grabberStatus & GRABBING_STOP) != 0) {
248: return ((grabberStatus & ALL_BITS) != 0);
249: }
250:
251: long start = System.currentTimeMillis();
252:
253: if (!isGrabbing) {
254: isGrabbing = true;
255: grabberStatus &= ~ImageObserver.ABORT;
256: producer.startProduction(this );
257: }
258: while ((grabberStatus & GRABBING_STOP) == 0) {
259: if (ms != 0) {
260: ms = start + ms - System.currentTimeMillis();
261: if (ms <= 0) {
262: break;
263: }
264: }
265: wait(ms);
266: }
267:
268: return ((grabberStatus & ALL_BITS) != 0);
269: }
270:
271: public void setDimensions(int w, int h) {
272: if (width < 0) {
273: width = w - X;
274: }
275: if (height < 0) {
276: height = h - Y;
277: }
278:
279: grabberStatus |= ImageObserver.WIDTH | ImageObserver.HEIGHT;
280:
281: if (width <= 0 || height <= 0) {
282: imageComplete(STATICIMAGEDONE);
283: return;
284: }
285:
286: if (isRGB && dataType == DATA_TYPE_UNDEFINED) {
287: iData = new int[width * height];
288: dataType = DATA_TYPE_INT;
289: scanline = width;
290: }
291: }
292:
293: public void setHints(int hints) {
294: return;
295: }
296:
297: public synchronized void imageComplete(int status) {
298: switch (status) {
299: case IMAGEABORTED:
300: grabberStatus |= ImageObserver.ABORT;
301: break;
302: case IMAGEERROR:
303: grabberStatus |= ImageObserver.ERROR | ImageObserver.ABORT;
304: break;
305: case SINGLEFRAMEDONE:
306: grabberStatus |= ImageObserver.FRAMEBITS;
307: break;
308: case STATICIMAGEDONE:
309: grabberStatus |= ImageObserver.ALLBITS;
310: break;
311: default:
312: // awt.26A=Incorrect ImageConsumer completion status
313: throw new IllegalArgumentException(Messages
314: .getString("awt.26A")); //$NON-NLS-1$
315: }
316: isGrabbing = false;
317: producer.removeConsumer(this );
318: notifyAll();
319: }
320:
321: public boolean grabPixels() throws InterruptedException {
322: return grabPixels(0);
323: }
324:
325: public synchronized void startGrabbing() {
326: if ((grabberStatus & GRABBING_STOP) != 0) {
327: return;
328: }
329: if (!isGrabbing) {
330: isGrabbing = true;
331: grabberStatus &= ~ImageObserver.ABORT;
332: producer.startProduction(this );
333: }
334: }
335:
336: public synchronized void abortGrabbing() {
337: imageComplete(IMAGEABORTED);
338: }
339:
340: public synchronized int status() {
341: return grabberStatus;
342: }
343:
344: public synchronized int getWidth() {
345: if (width < 0) {
346: return -1;
347: }
348: return width;
349: }
350:
351: public synchronized int getStatus() {
352: return grabberStatus;
353: }
354:
355: public synchronized int getHeight() {
356: if (height < 0) {
357: return -1;
358: }
359: return height;
360: }
361:
362: private void initialize(ImageProducer ip, int x, int y, int w,
363: int h, int pixels[], int off, int scansize, boolean forceRGB) {
364:
365: producer = ip;
366: X = x;
367: Y = y;
368: width = w;
369: height = h;
370: iData = pixels;
371: dataType = (pixels == null) ? DATA_TYPE_UNDEFINED
372: : DATA_TYPE_INT;
373: offset = off;
374: scanline = scansize;
375: if (forceRGB) {
376: cm = ColorModel.getRGBdefault();
377: isRGB = true;
378: }
379: }
380:
381: /**
382: * Force pixels to INT RGB mode
383: */
384: private void forceToRGB() {
385: if (isRGB)
386: return;
387:
388: switch (dataType) {
389: case DATA_TYPE_BYTE:
390: iData = new int[width * height];
391: for (int i = 0; i < iData.length; i++) {
392: iData[i] = cm.getRGB(bData[i] & 0xff);
393: }
394: dataType = DATA_TYPE_INT;
395: bData = null;
396: break;
397:
398: case DATA_TYPE_INT:
399: int buff[] = new int[width * height];
400: for (int i = 0; i < iData.length; i++) {
401: buff[i] = cm.getRGB(iData[i]);
402: }
403: iData = buff;
404: break;
405: }
406: offset = 0;
407: scanline = width;
408: cm = ColorModel.getRGBdefault();
409: isRGB = true;
410: }
411:
412: }
|