1 /*
2 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
94 * // Send the new data to the interested ImageConsumers
95 * source.newPixels(x, y, w, h);
96 * }
97 * }
98 *
99 * }</pre>
100 *
101 * @see ImageProducer
102 *
103 * @author Jim Graham
104 * @author Animation capabilities inspired by the
105 * MemoryAnimationSource class written by Garth Dickie
106 */
107 public class MemoryImageSource implements ImageProducer {
108 int width;
109 int height;
110 ColorModel model;
111 Object pixels;
112 int pixeloffset;
113 int pixelscan;
114 Hashtable properties;
115 Vector theConsumers = new Vector();
116 boolean animating;
117 boolean fullbuffers;
118
119 /**
120 * Constructs an ImageProducer object which uses an array of bytes
121 * to produce data for an Image object.
122 * @param w the width of the rectangle of pixels
123 * @param h the height of the rectangle of pixels
124 * @param cm the specified <code>ColorModel</code>
125 * @param pix an array of pixels
126 * @param off the offset into the array of where to store the
127 * first pixel
128 * @param scan the distance from one row of pixels to the next in
129 * the array
130 * @see java.awt.Component#createImage
131 */
132 public MemoryImageSource(int w, int h, ColorModel cm,
133 byte[] pix, int off, int scan) {
134 initialize(w, h, cm, (Object) pix, off, scan, null);
135 }
180 * @param w the width of the rectangle of pixels
181 * @param h the height of the rectangle of pixels
182 * @param cm the specified <code>ColorModel</code>
183 * @param pix an array of pixels
184 * @param off the offset into the array of where to store the
185 * first pixel
186 * @param scan the distance from one row of pixels to the next in
187 * the array
188 * @param props a list of properties that the <code>ImageProducer</code>
189 * uses to process an image
190 * @see java.awt.Component#createImage
191 */
192 public MemoryImageSource(int w, int h, ColorModel cm,
193 int[] pix, int off, int scan,
194 Hashtable<?,?> props)
195 {
196 initialize(w, h, cm, (Object) pix, off, scan, props);
197 }
198
199 private void initialize(int w, int h, ColorModel cm,
200 Object pix, int off, int scan, Hashtable props) {
201 width = w;
202 height = h;
203 model = cm;
204 pixels = pix;
205 pixeloffset = off;
206 pixelscan = scan;
207 if (props == null) {
208 props = new Hashtable();
209 }
210 properties = props;
211 }
212
213 /**
214 * Constructs an ImageProducer object which uses an array of integers
215 * in the default RGB ColorModel to produce data for an Image object.
216 * @param w the width of the rectangle of pixels
217 * @param h the height of the rectangle of pixels
218 * @param pix an array of pixels
219 * @param off the offset into the array of where to store the
220 * first pixel
221 * @param scan the distance from one row of pixels to the next in
222 * the array
223 * @see java.awt.Component#createImage
224 * @see ColorModel#getRGBdefault
225 */
226 public MemoryImageSource(int w, int h, int pix[], int off, int scan) {
227 initialize(w, h, ColorModel.getRGBdefault(),
228 (Object) pix, off, scan, null);
326 // Ignored. The data is either single frame and already in TDLR
327 // format or it is multi-frame and TDLR resends aren't critical.
328 }
329
330 /**
331 * Changes this memory image into a multi-frame animation or a
332 * single-frame static image depending on the animated parameter.
333 * <p>This method should be called immediately after the
334 * MemoryImageSource is constructed and before an image is
335 * created with it to ensure that all ImageConsumers will
336 * receive the correct multi-frame data. If an ImageConsumer
337 * is added to this ImageProducer before this flag is set then
338 * that ImageConsumer will see only a snapshot of the pixel
339 * data that was available when it connected.
340 * @param animated <code>true</code> if the image is a
341 * multi-frame animation
342 */
343 public synchronized void setAnimated(boolean animated) {
344 this.animating = animated;
345 if (!animating) {
346 Enumeration enum_ = theConsumers.elements();
347 while (enum_.hasMoreElements()) {
348 ImageConsumer ic = (ImageConsumer) enum_.nextElement();
349 ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
350 if (isConsumer(ic)) {
351 ic.imageComplete(ImageConsumer.IMAGEERROR);
352 }
353 }
354 theConsumers.removeAllElements();
355 }
356 }
357
358 /**
359 * Specifies whether this animated memory image should always be
360 * updated by sending the complete buffer of pixels whenever
361 * there is a change.
362 * This flag is ignored if the animation flag is not turned on
363 * through the setAnimated() method.
364 * <p>This method should be called immediately after the
365 * MemoryImageSource is constructed and before an image is
366 * created with it to ensure that all ImageConsumers will
367 * receive the correct pixel delivery hints.
368 * @param fullbuffers <code>true</code> if the complete pixel
369 * buffer should always
370 * be sent
371 * @see #setAnimated
372 */
373 public synchronized void setFullBufferUpdates(boolean fullbuffers) {
374 if (this.fullbuffers == fullbuffers) {
375 return;
376 }
377 this.fullbuffers = fullbuffers;
378 if (animating) {
379 Enumeration enum_ = theConsumers.elements();
380 while (enum_.hasMoreElements()) {
381 ImageConsumer ic = (ImageConsumer) enum_.nextElement();
382 ic.setHints(fullbuffers
383 ? (ImageConsumer.TOPDOWNLEFTRIGHT |
384 ImageConsumer.COMPLETESCANLINES)
385 : ImageConsumer.RANDOMPIXELORDER);
386 }
387 }
388 }
389
390 /**
391 * Sends a whole new buffer of pixels to any ImageConsumers that
392 * are currently interested in the data for this image and notify
393 * them that an animation frame is complete.
394 * This method only has effect if the animation flag has been
395 * turned on through the setAnimated() method.
396 * @see #newPixels(int, int, int, int, boolean)
397 * @see ImageConsumer
398 * @see #setAnimated
399 */
400 public void newPixels() {
401 newPixels(0, 0, width, height, true);
457 h = height;
458 } else {
459 if (x < 0) {
460 w += x;
461 x = 0;
462 }
463 if (x + w > width) {
464 w = width - x;
465 }
466 if (y < 0) {
467 h += y;
468 y = 0;
469 }
470 if (y + h > height) {
471 h = height - y;
472 }
473 }
474 if ((w <= 0 || h <= 0) && !framenotify) {
475 return;
476 }
477 Enumeration enum_ = theConsumers.elements();
478 while (enum_.hasMoreElements()) {
479 ImageConsumer ic = (ImageConsumer) enum_.nextElement();
480 if (w > 0 && h > 0) {
481 sendPixels(ic, x, y, w, h);
482 }
483 if (framenotify && isConsumer(ic)) {
484 ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
485 }
486 }
487 }
488 }
489
490 /**
491 * Changes to a new byte array to hold the pixels for this image.
492 * If the animation flag has been turned on through the setAnimated()
493 * method, then the new pixels will be immediately delivered to any
494 * ImageConsumers that are currently interested in the data for
495 * this image.
496 * @param newpix the new pixel array
497 * @param newmodel the specified <code>ColorModel</code>
498 * @param offset the offset into the array
499 * @param scansize the distance from one row of pixels to the next in
|
1 /*
2 * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
94 * // Send the new data to the interested ImageConsumers
95 * source.newPixels(x, y, w, h);
96 * }
97 * }
98 *
99 * }</pre>
100 *
101 * @see ImageProducer
102 *
103 * @author Jim Graham
104 * @author Animation capabilities inspired by the
105 * MemoryAnimationSource class written by Garth Dickie
106 */
107 public class MemoryImageSource implements ImageProducer {
108 int width;
109 int height;
110 ColorModel model;
111 Object pixels;
112 int pixeloffset;
113 int pixelscan;
114 Hashtable<?, ?> properties;
115 Vector<ImageConsumer> theConsumers = new Vector<>();
116 boolean animating;
117 boolean fullbuffers;
118
119 /**
120 * Constructs an ImageProducer object which uses an array of bytes
121 * to produce data for an Image object.
122 * @param w the width of the rectangle of pixels
123 * @param h the height of the rectangle of pixels
124 * @param cm the specified <code>ColorModel</code>
125 * @param pix an array of pixels
126 * @param off the offset into the array of where to store the
127 * first pixel
128 * @param scan the distance from one row of pixels to the next in
129 * the array
130 * @see java.awt.Component#createImage
131 */
132 public MemoryImageSource(int w, int h, ColorModel cm,
133 byte[] pix, int off, int scan) {
134 initialize(w, h, cm, (Object) pix, off, scan, null);
135 }
180 * @param w the width of the rectangle of pixels
181 * @param h the height of the rectangle of pixels
182 * @param cm the specified <code>ColorModel</code>
183 * @param pix an array of pixels
184 * @param off the offset into the array of where to store the
185 * first pixel
186 * @param scan the distance from one row of pixels to the next in
187 * the array
188 * @param props a list of properties that the <code>ImageProducer</code>
189 * uses to process an image
190 * @see java.awt.Component#createImage
191 */
192 public MemoryImageSource(int w, int h, ColorModel cm,
193 int[] pix, int off, int scan,
194 Hashtable<?,?> props)
195 {
196 initialize(w, h, cm, (Object) pix, off, scan, props);
197 }
198
199 private void initialize(int w, int h, ColorModel cm,
200 Object pix, int off, int scan, Hashtable<?,?> props) {
201 width = w;
202 height = h;
203 model = cm;
204 pixels = pix;
205 pixeloffset = off;
206 pixelscan = scan;
207 if (props == null) {
208 props = new Hashtable<>();
209 }
210 properties = props;
211 }
212
213 /**
214 * Constructs an ImageProducer object which uses an array of integers
215 * in the default RGB ColorModel to produce data for an Image object.
216 * @param w the width of the rectangle of pixels
217 * @param h the height of the rectangle of pixels
218 * @param pix an array of pixels
219 * @param off the offset into the array of where to store the
220 * first pixel
221 * @param scan the distance from one row of pixels to the next in
222 * the array
223 * @see java.awt.Component#createImage
224 * @see ColorModel#getRGBdefault
225 */
226 public MemoryImageSource(int w, int h, int pix[], int off, int scan) {
227 initialize(w, h, ColorModel.getRGBdefault(),
228 (Object) pix, off, scan, null);
326 // Ignored. The data is either single frame and already in TDLR
327 // format or it is multi-frame and TDLR resends aren't critical.
328 }
329
330 /**
331 * Changes this memory image into a multi-frame animation or a
332 * single-frame static image depending on the animated parameter.
333 * <p>This method should be called immediately after the
334 * MemoryImageSource is constructed and before an image is
335 * created with it to ensure that all ImageConsumers will
336 * receive the correct multi-frame data. If an ImageConsumer
337 * is added to this ImageProducer before this flag is set then
338 * that ImageConsumer will see only a snapshot of the pixel
339 * data that was available when it connected.
340 * @param animated <code>true</code> if the image is a
341 * multi-frame animation
342 */
343 public synchronized void setAnimated(boolean animated) {
344 this.animating = animated;
345 if (!animating) {
346 Enumeration<ImageConsumer> enum_ = theConsumers.elements();
347 while (enum_.hasMoreElements()) {
348 ImageConsumer ic = enum_.nextElement();
349 ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
350 if (isConsumer(ic)) {
351 ic.imageComplete(ImageConsumer.IMAGEERROR);
352 }
353 }
354 theConsumers.removeAllElements();
355 }
356 }
357
358 /**
359 * Specifies whether this animated memory image should always be
360 * updated by sending the complete buffer of pixels whenever
361 * there is a change.
362 * This flag is ignored if the animation flag is not turned on
363 * through the setAnimated() method.
364 * <p>This method should be called immediately after the
365 * MemoryImageSource is constructed and before an image is
366 * created with it to ensure that all ImageConsumers will
367 * receive the correct pixel delivery hints.
368 * @param fullbuffers <code>true</code> if the complete pixel
369 * buffer should always
370 * be sent
371 * @see #setAnimated
372 */
373 public synchronized void setFullBufferUpdates(boolean fullbuffers) {
374 if (this.fullbuffers == fullbuffers) {
375 return;
376 }
377 this.fullbuffers = fullbuffers;
378 if (animating) {
379 Enumeration<ImageConsumer> enum_ = theConsumers.elements();
380 while (enum_.hasMoreElements()) {
381 ImageConsumer ic = enum_.nextElement();
382 ic.setHints(fullbuffers
383 ? (ImageConsumer.TOPDOWNLEFTRIGHT |
384 ImageConsumer.COMPLETESCANLINES)
385 : ImageConsumer.RANDOMPIXELORDER);
386 }
387 }
388 }
389
390 /**
391 * Sends a whole new buffer of pixels to any ImageConsumers that
392 * are currently interested in the data for this image and notify
393 * them that an animation frame is complete.
394 * This method only has effect if the animation flag has been
395 * turned on through the setAnimated() method.
396 * @see #newPixels(int, int, int, int, boolean)
397 * @see ImageConsumer
398 * @see #setAnimated
399 */
400 public void newPixels() {
401 newPixels(0, 0, width, height, true);
457 h = height;
458 } else {
459 if (x < 0) {
460 w += x;
461 x = 0;
462 }
463 if (x + w > width) {
464 w = width - x;
465 }
466 if (y < 0) {
467 h += y;
468 y = 0;
469 }
470 if (y + h > height) {
471 h = height - y;
472 }
473 }
474 if ((w <= 0 || h <= 0) && !framenotify) {
475 return;
476 }
477 Enumeration<ImageConsumer> enum_ = theConsumers.elements();
478 while (enum_.hasMoreElements()) {
479 ImageConsumer ic = enum_.nextElement();
480 if (w > 0 && h > 0) {
481 sendPixels(ic, x, y, w, h);
482 }
483 if (framenotify && isConsumer(ic)) {
484 ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
485 }
486 }
487 }
488 }
489
490 /**
491 * Changes to a new byte array to hold the pixels for this image.
492 * If the animation flag has been turned on through the setAnimated()
493 * method, then the new pixels will be immediately delivered to any
494 * ImageConsumers that are currently interested in the data for
495 * this image.
496 * @param newpix the new pixel array
497 * @param newmodel the specified <code>ColorModel</code>
498 * @param offset the offset into the array
499 * @param scansize the distance from one row of pixels to the next in
|