1 |
771 |
jeremybenn |
/* PixelGrabber.java -- retrieve a subset of an image's data
|
2 |
|
|
Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
|
3 |
|
|
|
4 |
|
|
This file is part of GNU Classpath.
|
5 |
|
|
|
6 |
|
|
GNU Classpath is free software; you can redistribute it and/or modify
|
7 |
|
|
it under the terms of the GNU General Public License as published by
|
8 |
|
|
the Free Software Foundation; either version 2, or (at your option)
|
9 |
|
|
any later version.
|
10 |
|
|
|
11 |
|
|
GNU Classpath is distributed in the hope that it will be useful, but
|
12 |
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
|
|
General Public License for more details.
|
15 |
|
|
|
16 |
|
|
You should have received a copy of the GNU General Public License
|
17 |
|
|
along with GNU Classpath; see the file COPYING. If not, write to the
|
18 |
|
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 |
|
|
02110-1301 USA.
|
20 |
|
|
|
21 |
|
|
Linking this library statically or dynamically with other modules is
|
22 |
|
|
making a combined work based on this library. Thus, the terms and
|
23 |
|
|
conditions of the GNU General Public License cover the whole
|
24 |
|
|
combination.
|
25 |
|
|
|
26 |
|
|
As a special exception, the copyright holders of this library give you
|
27 |
|
|
permission to link this library with independent modules to produce an
|
28 |
|
|
executable, regardless of the license terms of these independent
|
29 |
|
|
modules, and to copy and distribute the resulting executable under
|
30 |
|
|
terms of your choice, provided that you also meet, for each linked
|
31 |
|
|
independent module, the terms and conditions of the license of that
|
32 |
|
|
module. An independent module is a module which is not derived from
|
33 |
|
|
or based on this library. If you modify this library, you may extend
|
34 |
|
|
this exception to your version of the library, but you are not
|
35 |
|
|
obligated to do so. If you do not wish to do so, delete this
|
36 |
|
|
exception statement from your version. */
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
package java.awt.image;
|
40 |
|
|
|
41 |
|
|
import java.awt.Image;
|
42 |
|
|
import java.util.Hashtable;
|
43 |
|
|
|
44 |
|
|
/**
|
45 |
|
|
* PixelGrabber is an ImageConsumer that extracts a rectangular region
|
46 |
|
|
* of pixels from an Image.
|
47 |
|
|
*/
|
48 |
|
|
public class PixelGrabber implements ImageConsumer
|
49 |
|
|
{
|
50 |
|
|
int x, y, offset;
|
51 |
|
|
int width = -1;
|
52 |
|
|
int height = -1;
|
53 |
|
|
int scansize = -1;
|
54 |
|
|
boolean forceRGB = true;
|
55 |
|
|
|
56 |
|
|
ColorModel model = ColorModel.getRGBdefault();
|
57 |
|
|
int hints;
|
58 |
|
|
Hashtable<?,?> props;
|
59 |
|
|
|
60 |
|
|
int int_pixel_buffer[];
|
61 |
|
|
boolean ints_delivered = false;
|
62 |
|
|
byte byte_pixel_buffer[];
|
63 |
|
|
boolean bytes_delivered = false;
|
64 |
|
|
|
65 |
|
|
ImageProducer ip;
|
66 |
|
|
int observerStatus;
|
67 |
|
|
int consumerStatus;
|
68 |
|
|
|
69 |
|
|
private Thread grabberThread;
|
70 |
|
|
boolean grabbing = false;
|
71 |
|
|
|
72 |
|
|
/**
|
73 |
|
|
* Construct a PixelGrabber that will retrieve RGB data from a given
|
74 |
|
|
* Image.
|
75 |
|
|
*
|
76 |
|
|
* The RGB data will be retrieved from a rectangular region
|
77 |
|
|
* <code>(x, y, w, h)</code> within the image. The data will be
|
78 |
|
|
* stored in the provided <code>pix</code> array, which must have
|
79 |
|
|
* been initialized to a size of at least <code>w * h</code>. The
|
80 |
|
|
* data for a pixel (m, n) in the grab rectangle will be stored at
|
81 |
|
|
* <code>pix[(n - y) * scansize + (m - x) + off]</code>.
|
82 |
|
|
*
|
83 |
|
|
* @param img the Image from which to grab pixels
|
84 |
|
|
* @param x the x coordinate, relative to <code>img</code>'s
|
85 |
|
|
* top-left corner, of the grab rectangle's top-left pixel
|
86 |
|
|
* @param y the y coordinate, relative to <code>img</code>'s
|
87 |
|
|
* top-left corner, of the grab rectangle's top-left pixel
|
88 |
|
|
* @param w the width of the grab rectangle, in pixels
|
89 |
|
|
* @param h the height of the grab rectangle, in pixels
|
90 |
|
|
* @param pix the array in which to store grabbed RGB pixel data
|
91 |
|
|
* @param off the offset into the <code>pix</code> array at which to
|
92 |
|
|
* start storing RGB data
|
93 |
|
|
* @param scansize a set of <code>scansize</code> consecutive
|
94 |
|
|
* elements in the <code>pix</code> array represents one row of
|
95 |
|
|
* pixels in the grab rectangle
|
96 |
|
|
*/
|
97 |
|
|
public PixelGrabber(Image img, int x, int y, int w, int h,
|
98 |
|
|
int pix[], int off, int scansize)
|
99 |
|
|
{
|
100 |
|
|
this (img.getSource(), x, y, w, h, pix, off, scansize);
|
101 |
|
|
}
|
102 |
|
|
|
103 |
|
|
/**
|
104 |
|
|
* Construct a PixelGrabber that will retrieve RGB data from a given
|
105 |
|
|
* ImageProducer.
|
106 |
|
|
*
|
107 |
|
|
* The RGB data will be retrieved from a rectangular region
|
108 |
|
|
* <code>(x, y, w, h)</code> within the image produced by
|
109 |
|
|
* <code>ip</code>. The data will be stored in the provided
|
110 |
|
|
* <code>pix</code> array, which must have been initialized to a
|
111 |
|
|
* size of at least <code>w * h</code>. The data for a pixel (m, n)
|
112 |
|
|
* in the grab rectangle will be stored at
|
113 |
|
|
* <code>pix[(n - y) * scansize + (m - x) + off]</code>.
|
114 |
|
|
*
|
115 |
|
|
* @param ip the ImageProducer from which to grab pixels. This can
|
116 |
|
|
* be null.
|
117 |
|
|
* @param x the x coordinate of the grab rectangle's top-left pixel,
|
118 |
|
|
* specified relative to the top-left corner of the image produced
|
119 |
|
|
* by <code>ip</code>
|
120 |
|
|
* @param y the y coordinate of the grab rectangle's top-left pixel,
|
121 |
|
|
* specified relative to the top-left corner of the image produced
|
122 |
|
|
* by <code>ip</code>
|
123 |
|
|
* @param w the width of the grab rectangle, in pixels
|
124 |
|
|
* @param h the height of the grab rectangle, in pixels
|
125 |
|
|
* @param pix the array in which to store grabbed RGB pixel data
|
126 |
|
|
* @param off the offset into the <code>pix</code> array at which to
|
127 |
|
|
* start storing RGB data
|
128 |
|
|
* @param scansize a set of <code>scansize</code> consecutive
|
129 |
|
|
* elements in the <code>pix</code> array represents one row of
|
130 |
|
|
* pixels in the grab rectangle
|
131 |
|
|
*/
|
132 |
|
|
public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
|
133 |
|
|
int pix[], int off, int scansize)
|
134 |
|
|
{
|
135 |
|
|
this.ip = ip;
|
136 |
|
|
this.x = x;
|
137 |
|
|
this.y = y;
|
138 |
|
|
this.width = w;
|
139 |
|
|
this.height = h;
|
140 |
|
|
this.offset = off;
|
141 |
|
|
this.scansize = scansize;
|
142 |
|
|
|
143 |
|
|
int_pixel_buffer = pix;
|
144 |
|
|
// Initialize the byte array in case ip sends us byte-formatted
|
145 |
|
|
// pixel data.
|
146 |
|
|
byte_pixel_buffer = new byte[pix.length * 4];
|
147 |
|
|
}
|
148 |
|
|
|
149 |
|
|
/**
|
150 |
|
|
* Construct a PixelGrabber that will retrieve data from a given
|
151 |
|
|
* Image.
|
152 |
|
|
*
|
153 |
|
|
* The RGB data will be retrieved from a rectangular region
|
154 |
|
|
* <code>(x, y, w, h)</code> within the image. The data will be
|
155 |
|
|
* stored in an internal array which can be accessed by calling
|
156 |
|
|
* <code>getPixels</code>. The data for a pixel (m, n) in the grab
|
157 |
|
|
* rectangle will be stored in the returned array at index
|
158 |
|
|
* <code>(n - y) * scansize + (m - x) + off</code>.
|
159 |
|
|
* If forceRGB is false, then the returned data will be not be
|
160 |
|
|
* converted to RGB from its format in <code>img</code>.
|
161 |
|
|
*
|
162 |
|
|
* If <code>w</code> is negative, the width of the grab region will
|
163 |
|
|
* be from x to the right edge of the image. Likewise, if
|
164 |
|
|
* <code>h</code> is negative, the height of the grab region will be
|
165 |
|
|
* from y to the bottom edge of the image.
|
166 |
|
|
*
|
167 |
|
|
* @param img the Image from which to grab pixels
|
168 |
|
|
* @param x the x coordinate, relative to <code>img</code>'s
|
169 |
|
|
* top-left corner, of the grab rectangle's top-left pixel
|
170 |
|
|
* @param y the y coordinate, relative to <code>img</code>'s
|
171 |
|
|
* top-left corner, of the grab rectangle's top-left pixel
|
172 |
|
|
* @param w the width of the grab rectangle, in pixels
|
173 |
|
|
* @param h the height of the grab rectangle, in pixels
|
174 |
|
|
* @param forceRGB true to force conversion of the rectangular
|
175 |
|
|
* region's pixel data to RGB
|
176 |
|
|
*/
|
177 |
|
|
public PixelGrabber(Image img,
|
178 |
|
|
int x, int y,
|
179 |
|
|
int w, int h,
|
180 |
|
|
boolean forceRGB)
|
181 |
|
|
{
|
182 |
|
|
this.ip = img.getSource();
|
183 |
|
|
|
184 |
|
|
if (this.ip == null)
|
185 |
|
|
throw new NullPointerException("The ImageProducer must not be null.");
|
186 |
|
|
|
187 |
|
|
this.x = x;
|
188 |
|
|
this.y = y;
|
189 |
|
|
width = w;
|
190 |
|
|
height = h;
|
191 |
|
|
// If width or height is negative, postpone pixel buffer
|
192 |
|
|
// initialization until setDimensions is called back by ip.
|
193 |
|
|
if (width >= 0 && height >= 0)
|
194 |
|
|
{
|
195 |
|
|
int_pixel_buffer = new int[width * height];
|
196 |
|
|
byte_pixel_buffer = new byte[width * height];
|
197 |
|
|
}
|
198 |
|
|
this.forceRGB = forceRGB;
|
199 |
|
|
}
|
200 |
|
|
|
201 |
|
|
/**
|
202 |
|
|
* Start grabbing pixels.
|
203 |
|
|
*
|
204 |
|
|
* Spawns an image production thread that calls back to this
|
205 |
|
|
* PixelGrabber's ImageConsumer methods.
|
206 |
|
|
*/
|
207 |
|
|
public synchronized void startGrabbing()
|
208 |
|
|
{
|
209 |
|
|
// Make sure we're not already grabbing.
|
210 |
|
|
if (grabbing == false)
|
211 |
|
|
{
|
212 |
|
|
grabbing = true;
|
213 |
|
|
grabberThread = new Thread ()
|
214 |
|
|
{
|
215 |
|
|
public void run ()
|
216 |
|
|
{
|
217 |
|
|
try
|
218 |
|
|
{
|
219 |
|
|
ip.startProduction (PixelGrabber.this);
|
220 |
|
|
}
|
221 |
|
|
catch (Exception ex)
|
222 |
|
|
{
|
223 |
|
|
imageComplete(ImageConsumer.IMAGEABORTED);
|
224 |
|
|
}
|
225 |
|
|
}
|
226 |
|
|
};
|
227 |
|
|
grabberThread.start ();
|
228 |
|
|
}
|
229 |
|
|
}
|
230 |
|
|
|
231 |
|
|
/**
|
232 |
|
|
* Abort pixel grabbing.
|
233 |
|
|
*/
|
234 |
|
|
public synchronized void abortGrabbing()
|
235 |
|
|
{
|
236 |
|
|
if (grabbing)
|
237 |
|
|
{
|
238 |
|
|
// Interrupt the grabbing thread.
|
239 |
|
|
Thread moribund = grabberThread;
|
240 |
|
|
grabberThread = null;
|
241 |
|
|
moribund.interrupt();
|
242 |
|
|
|
243 |
|
|
imageComplete (ImageConsumer.IMAGEABORTED);
|
244 |
|
|
}
|
245 |
|
|
}
|
246 |
|
|
|
247 |
|
|
/**
|
248 |
|
|
* Have our Image or ImageProducer start sending us pixels via our
|
249 |
|
|
* ImageConsumer methods and wait for all pixels in the grab
|
250 |
|
|
* rectangle to be delivered.
|
251 |
|
|
*
|
252 |
|
|
* @return true if successful, false on abort or error
|
253 |
|
|
*
|
254 |
|
|
* @throws InterruptedException if interrupted by another thread.
|
255 |
|
|
*/
|
256 |
|
|
public synchronized boolean grabPixels() throws InterruptedException
|
257 |
|
|
{
|
258 |
|
|
return grabPixels(0);
|
259 |
|
|
}
|
260 |
|
|
|
261 |
|
|
/**
|
262 |
|
|
* grabPixels's behavior depends on the value of <code>ms</code>.
|
263 |
|
|
*
|
264 |
|
|
* If ms < 0, return true if all pixels from the source image have
|
265 |
|
|
* been delivered, false otherwise. Do not wait.
|
266 |
|
|
*
|
267 |
|
|
* If ms >= 0 then we request that our Image or ImageProducer start
|
268 |
|
|
* delivering pixels to us via our ImageConsumer methods.
|
269 |
|
|
*
|
270 |
|
|
* If ms > 0, wait at most <code>ms</code> milliseconds for
|
271 |
|
|
* delivery of all pixels within the grab rectangle.
|
272 |
|
|
*
|
273 |
|
|
* If ms == 0, wait until all pixels have been delivered.
|
274 |
|
|
*
|
275 |
|
|
* @return true if all pixels from the source image have been
|
276 |
|
|
* delivered, false otherwise
|
277 |
|
|
*
|
278 |
|
|
* @throws InterruptedException if this thread is interrupted while
|
279 |
|
|
* we are waiting for pixels to be delivered
|
280 |
|
|
*/
|
281 |
|
|
public synchronized boolean grabPixels(long ms) throws InterruptedException
|
282 |
|
|
{
|
283 |
|
|
if (ms < 0)
|
284 |
|
|
return ((observerStatus & (ImageObserver.FRAMEBITS
|
285 |
|
|
| ImageObserver.ALLBITS)) != 0);
|
286 |
|
|
|
287 |
|
|
// Spawn a new ImageProducer thread to send us the image data via
|
288 |
|
|
// our ImageConsumer methods.
|
289 |
|
|
startGrabbing();
|
290 |
|
|
|
291 |
|
|
if (ms > 0)
|
292 |
|
|
{
|
293 |
|
|
long stop_time = System.currentTimeMillis() + ms;
|
294 |
|
|
long time_remaining;
|
295 |
|
|
while (grabbing)
|
296 |
|
|
{
|
297 |
|
|
time_remaining = stop_time - System.currentTimeMillis();
|
298 |
|
|
if (time_remaining <= 0)
|
299 |
|
|
break;
|
300 |
|
|
wait (time_remaining);
|
301 |
|
|
}
|
302 |
|
|
abortGrabbing ();
|
303 |
|
|
}
|
304 |
|
|
else
|
305 |
|
|
wait ();
|
306 |
|
|
|
307 |
|
|
// If consumerStatus is non-zero then the image is done loading or
|
308 |
|
|
// an error has occurred.
|
309 |
|
|
if (consumerStatus != 0)
|
310 |
|
|
return setObserverStatus ();
|
311 |
|
|
|
312 |
|
|
return ((observerStatus & (ImageObserver.FRAMEBITS
|
313 |
|
|
| ImageObserver.ALLBITS)) != 0);
|
314 |
|
|
}
|
315 |
|
|
|
316 |
|
|
// Set observer status flags based on the current consumer status
|
317 |
|
|
// flags. Return true if the consumer flags indicate that the
|
318 |
|
|
// image was loaded successfully, or false otherwise.
|
319 |
|
|
private synchronized boolean setObserverStatus ()
|
320 |
|
|
{
|
321 |
|
|
boolean retval = false;
|
322 |
|
|
|
323 |
|
|
if ((consumerStatus & IMAGEERROR) != 0)
|
324 |
|
|
observerStatus |= ImageObserver.ERROR;
|
325 |
|
|
|
326 |
|
|
if ((consumerStatus & IMAGEABORTED) != 0)
|
327 |
|
|
observerStatus |= ImageObserver.ABORT;
|
328 |
|
|
|
329 |
|
|
if ((consumerStatus & STATICIMAGEDONE) != 0)
|
330 |
|
|
{
|
331 |
|
|
observerStatus |= ImageObserver.ALLBITS;
|
332 |
|
|
retval = true;
|
333 |
|
|
}
|
334 |
|
|
|
335 |
|
|
if ((consumerStatus & SINGLEFRAMEDONE) != 0)
|
336 |
|
|
{
|
337 |
|
|
observerStatus |= ImageObserver.FRAMEBITS;
|
338 |
|
|
retval = true;
|
339 |
|
|
}
|
340 |
|
|
|
341 |
|
|
return retval;
|
342 |
|
|
}
|
343 |
|
|
|
344 |
|
|
/**
|
345 |
|
|
* @return the status of the pixel grabbing thread, represented by a
|
346 |
|
|
* bitwise OR of ImageObserver flags
|
347 |
|
|
*/
|
348 |
|
|
public synchronized int getStatus()
|
349 |
|
|
{
|
350 |
|
|
return observerStatus;
|
351 |
|
|
}
|
352 |
|
|
|
353 |
|
|
/**
|
354 |
|
|
* @return the width of the grab rectangle in pixels, or a negative
|
355 |
|
|
* number if the ImageProducer has not yet called our setDimensions
|
356 |
|
|
* method
|
357 |
|
|
*/
|
358 |
|
|
public synchronized int getWidth()
|
359 |
|
|
{
|
360 |
|
|
return width;
|
361 |
|
|
}
|
362 |
|
|
|
363 |
|
|
/**
|
364 |
|
|
* @return the height of the grab rectangle in pixels, or a negative
|
365 |
|
|
* number if the ImageProducer has not yet called our setDimensions
|
366 |
|
|
* method
|
367 |
|
|
*/
|
368 |
|
|
public synchronized int getHeight()
|
369 |
|
|
{
|
370 |
|
|
return height;
|
371 |
|
|
}
|
372 |
|
|
|
373 |
|
|
/**
|
374 |
|
|
* @return a byte array of pixel data if ImageProducer delivered
|
375 |
|
|
* pixel data using the byte[] variant of setPixels, or an int array
|
376 |
|
|
* otherwise
|
377 |
|
|
*/
|
378 |
|
|
public synchronized Object getPixels()
|
379 |
|
|
{
|
380 |
|
|
if (ints_delivered)
|
381 |
|
|
return int_pixel_buffer;
|
382 |
|
|
else if (bytes_delivered)
|
383 |
|
|
return byte_pixel_buffer;
|
384 |
|
|
else
|
385 |
|
|
return null;
|
386 |
|
|
}
|
387 |
|
|
|
388 |
|
|
/**
|
389 |
|
|
* @return the ColorModel currently being used for the majority of
|
390 |
|
|
* pixel data conversions
|
391 |
|
|
*/
|
392 |
|
|
public synchronized ColorModel getColorModel()
|
393 |
|
|
{
|
394 |
|
|
return model;
|
395 |
|
|
}
|
396 |
|
|
|
397 |
|
|
/**
|
398 |
|
|
* Our <code>ImageProducer</code> calls this method to indicate the
|
399 |
|
|
* size of the image being produced.
|
400 |
|
|
*
|
401 |
|
|
* setDimensions is an ImageConsumer method. None of PixelGrabber's
|
402 |
|
|
* ImageConsumer methods should be called by code that instantiates
|
403 |
|
|
* a PixelGrabber. They are only made public so they can be called
|
404 |
|
|
* by the PixelGrabber's ImageProducer.
|
405 |
|
|
*
|
406 |
|
|
* @param width the width of the image
|
407 |
|
|
* @param height the height of the image
|
408 |
|
|
*/
|
409 |
|
|
public synchronized void setDimensions(int width, int height)
|
410 |
|
|
{
|
411 |
|
|
// Our width wasn't set when we were constructed. Set our width
|
412 |
|
|
// so that the grab region includes all pixels from x to the right
|
413 |
|
|
// edge of the source image.
|
414 |
|
|
if (this.width < 0)
|
415 |
|
|
this.width = width - x;
|
416 |
|
|
|
417 |
|
|
// Our height wasn't set when we were constructed. Set our height
|
418 |
|
|
// so that the grab region includes all pixels from y to the
|
419 |
|
|
// bottom edge of the source image.
|
420 |
|
|
if (this.height < 0)
|
421 |
|
|
this.height = height - y;
|
422 |
|
|
|
423 |
|
|
if (scansize < 0)
|
424 |
|
|
scansize = this.width;
|
425 |
|
|
|
426 |
|
|
if (int_pixel_buffer == null)
|
427 |
|
|
int_pixel_buffer = new int[this.width * this.height];
|
428 |
|
|
|
429 |
|
|
if (byte_pixel_buffer == null)
|
430 |
|
|
byte_pixel_buffer = new byte[this.width * this.height];
|
431 |
|
|
}
|
432 |
|
|
|
433 |
|
|
/**
|
434 |
|
|
* Our <code>ImageProducer</code> may call this method to send us a
|
435 |
|
|
* list of its image's properties.
|
436 |
|
|
*
|
437 |
|
|
* setProperties is an ImageConsumer method. None of PixelGrabber's
|
438 |
|
|
* ImageConsumer methods should be called by code that instantiates
|
439 |
|
|
* a PixelGrabber. They are only made public so they can be called
|
440 |
|
|
* by the PixelGrabber's ImageProducer.
|
441 |
|
|
*
|
442 |
|
|
* @param props a list of properties associated with the image being
|
443 |
|
|
* produced
|
444 |
|
|
*/
|
445 |
|
|
public synchronized void setProperties(Hashtable<?,?> props)
|
446 |
|
|
{
|
447 |
|
|
this.props = props;
|
448 |
|
|
}
|
449 |
|
|
|
450 |
|
|
/**
|
451 |
|
|
* Our ImageProducer will call <code>setColorModel</code> to
|
452 |
|
|
* indicate the model used by the majority of calls to
|
453 |
|
|
* <code>setPixels</code>. Each call to <code>setPixels</code>
|
454 |
|
|
* could however indicate a different <code>ColorModel</code>.
|
455 |
|
|
*
|
456 |
|
|
* setColorModel is an ImageConsumer method. None of PixelGrabber's
|
457 |
|
|
* ImageConsumer methods should be called by code that instantiates
|
458 |
|
|
* a PixelGrabber. They are only made public so they can be called
|
459 |
|
|
* by the PixelGrabber's ImageProducer.
|
460 |
|
|
*
|
461 |
|
|
* @param model the color model to be used most often by setPixels
|
462 |
|
|
*
|
463 |
|
|
* @see ColorModel
|
464 |
|
|
*/
|
465 |
|
|
public synchronized void setColorModel(ColorModel model)
|
466 |
|
|
{
|
467 |
|
|
this.model = model;
|
468 |
|
|
}
|
469 |
|
|
|
470 |
|
|
/**
|
471 |
|
|
* Our <code>ImageProducer</code> may call this method with a
|
472 |
|
|
* bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
|
473 |
|
|
* <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
|
474 |
|
|
* <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
|
475 |
|
|
*
|
476 |
|
|
* setHints is an ImageConsumer method. None of PixelGrabber's
|
477 |
|
|
* ImageConsumer methods should be called by code that instantiates
|
478 |
|
|
* a PixelGrabber. They are only made public so they can be called
|
479 |
|
|
* by the PixelGrabber's ImageProducer.
|
480 |
|
|
*
|
481 |
|
|
* @param flags a bit mask of hints
|
482 |
|
|
*/
|
483 |
|
|
public synchronized void setHints(int flags)
|
484 |
|
|
{
|
485 |
|
|
hints = flags;
|
486 |
|
|
}
|
487 |
|
|
|
488 |
|
|
/**
|
489 |
|
|
* Our ImageProducer calls setPixels to deliver a subset of its
|
490 |
|
|
* pixels.
|
491 |
|
|
*
|
492 |
|
|
* Each element of the pixels array represents one pixel. The
|
493 |
|
|
* pixel data is formatted according to the color model model.
|
494 |
|
|
* The x and y parameters are the coordinates of the rectangular
|
495 |
|
|
* region of pixels being delivered to this ImageConsumer,
|
496 |
|
|
* specified relative to the top left corner of the image being
|
497 |
|
|
* produced. Likewise, w and h are the pixel region's dimensions.
|
498 |
|
|
*
|
499 |
|
|
* @param x x coordinate of pixel block
|
500 |
|
|
* @param y y coordinate of pixel block
|
501 |
|
|
* @param w width of pixel block
|
502 |
|
|
* @param h height of pixel block
|
503 |
|
|
* @param model color model used to interpret pixel data
|
504 |
|
|
* @param pixels pixel block data
|
505 |
|
|
* @param offset offset into pixels array
|
506 |
|
|
* @param scansize width of one row in the pixel block
|
507 |
|
|
*/
|
508 |
|
|
public synchronized void setPixels(int x, int y, int w, int h,
|
509 |
|
|
ColorModel model, byte[] pixels,
|
510 |
|
|
int offset, int scansize)
|
511 |
|
|
{
|
512 |
|
|
ColorModel currentModel;
|
513 |
|
|
if (model != null)
|
514 |
|
|
currentModel = model;
|
515 |
|
|
else
|
516 |
|
|
currentModel = this.model;
|
517 |
|
|
|
518 |
|
|
for(int yp = y; yp < (y + h); yp++)
|
519 |
|
|
{
|
520 |
|
|
for(int xp = x; xp < (x + w); xp++)
|
521 |
|
|
{
|
522 |
|
|
// Check if the coordinates (xp, yp) are within the
|
523 |
|
|
// pixel block that we are grabbing.
|
524 |
|
|
if(xp >= this.x
|
525 |
|
|
&& yp >= this.y
|
526 |
|
|
&& xp < (this.x + this.width)
|
527 |
|
|
&& yp < (this.y + this.height))
|
528 |
|
|
{
|
529 |
|
|
int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
|
530 |
|
|
int p = (yp - y) * scansize + (xp - x) + offset;
|
531 |
|
|
if (forceRGB)
|
532 |
|
|
{
|
533 |
|
|
ints_delivered = true;
|
534 |
|
|
|
535 |
|
|
int_pixel_buffer[i] = currentModel.getRGB (pixels[p] & 0xFF);
|
536 |
|
|
}
|
537 |
|
|
else
|
538 |
|
|
{
|
539 |
|
|
bytes_delivered = true;
|
540 |
|
|
|
541 |
|
|
byte_pixel_buffer[i] = pixels[p];
|
542 |
|
|
}
|
543 |
|
|
}
|
544 |
|
|
}
|
545 |
|
|
}
|
546 |
|
|
}
|
547 |
|
|
|
548 |
|
|
/**
|
549 |
|
|
* Our ImageProducer calls setPixels to deliver a subset of its
|
550 |
|
|
* pixels.
|
551 |
|
|
*
|
552 |
|
|
* Each element of the pixels array represents one pixel. The
|
553 |
|
|
* pixel data is formatted according to the color model model.
|
554 |
|
|
* The x and y parameters are the coordinates of the rectangular
|
555 |
|
|
* region of pixels being delivered to this ImageConsumer,
|
556 |
|
|
* specified relative to the top left corner of the image being
|
557 |
|
|
* produced. Likewise, w and h are the pixel region's dimensions.
|
558 |
|
|
*
|
559 |
|
|
* @param x x coordinate of pixel block
|
560 |
|
|
* @param y y coordinate of pixel block
|
561 |
|
|
* @param w width of pixel block
|
562 |
|
|
* @param h height of pixel block
|
563 |
|
|
* @param model color model used to interpret pixel data
|
564 |
|
|
* @param pixels pixel block data
|
565 |
|
|
* @param offset offset into pixels array
|
566 |
|
|
* @param scansize width of one row in the pixel block
|
567 |
|
|
*/
|
568 |
|
|
public synchronized void setPixels(int x, int y, int w, int h,
|
569 |
|
|
ColorModel model, int[] pixels,
|
570 |
|
|
int offset, int scansize)
|
571 |
|
|
{
|
572 |
|
|
ColorModel currentModel;
|
573 |
|
|
if (model != null)
|
574 |
|
|
currentModel = model;
|
575 |
|
|
else
|
576 |
|
|
currentModel = this.model;
|
577 |
|
|
|
578 |
|
|
ints_delivered = true;
|
579 |
|
|
|
580 |
|
|
for(int yp = y; yp < (y + h); yp++)
|
581 |
|
|
{
|
582 |
|
|
for(int xp = x; xp < (x + w); xp++)
|
583 |
|
|
{
|
584 |
|
|
// Check if the coordinates (xp, yp) are within the
|
585 |
|
|
// pixel block that we are grabbing.
|
586 |
|
|
if(xp >= this.x
|
587 |
|
|
&& yp >= this.y
|
588 |
|
|
&& xp < (this.x + this.width)
|
589 |
|
|
&& yp < (this.y + this.height))
|
590 |
|
|
{
|
591 |
|
|
int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
|
592 |
|
|
int p = (yp - y) * scansize + (xp - x) + offset;
|
593 |
|
|
if (forceRGB)
|
594 |
|
|
int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
|
595 |
|
|
else
|
596 |
|
|
int_pixel_buffer[i] = pixels[p];
|
597 |
|
|
}
|
598 |
|
|
}
|
599 |
|
|
}
|
600 |
|
|
}
|
601 |
|
|
|
602 |
|
|
/**
|
603 |
|
|
* Our <code>ImageProducer</code> calls this method to inform us
|
604 |
|
|
* that a single frame or the entire image is complete. The method
|
605 |
|
|
* is also used to inform us of an error in loading or producing the
|
606 |
|
|
* image.
|
607 |
|
|
*
|
608 |
|
|
* @param status the status of image production, represented by a
|
609 |
|
|
* bitwise OR of ImageConsumer flags
|
610 |
|
|
*/
|
611 |
|
|
public synchronized void imageComplete(int status)
|
612 |
|
|
{
|
613 |
|
|
consumerStatus = status;
|
614 |
|
|
setObserverStatus ();
|
615 |
|
|
grabbing = false;
|
616 |
|
|
if (ip != null)
|
617 |
|
|
ip.removeConsumer (this);
|
618 |
|
|
|
619 |
|
|
notifyAll ();
|
620 |
|
|
}
|
621 |
|
|
|
622 |
|
|
/**
|
623 |
|
|
* @return the return value of getStatus
|
624 |
|
|
*
|
625 |
|
|
* @specnote The newer getStatus should be used in place of status.
|
626 |
|
|
*/
|
627 |
|
|
public synchronized int status()
|
628 |
|
|
{
|
629 |
|
|
return getStatus();
|
630 |
|
|
}
|
631 |
|
|
}
|