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