001 /* MemoryImageSource.java -- Java class for providing image data
002 Copyright (C) 1999, 2004, 2006, Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.awt.image;
040
041 import java.util.Hashtable;
042 import java.util.Vector;
043
044 /**
045 * An image producer that delivers image data from an array.
046 */
047 public class MemoryImageSource implements ImageProducer
048 {
049 private boolean animated = false;
050 private boolean fullbuffers = false;
051 private int[] pixeli;
052 private int width;
053 private int height;
054 private int offset;
055 private int scansize;
056 private byte[] pixelb;
057 private ColorModel cm;
058 private Hashtable props = new Hashtable();
059 private Vector consumers = new Vector();
060
061 /**
062 * Construct an image producer that reads image data from a byte
063 * array.
064 *
065 * @param w width of image
066 * @param h height of image
067 * @param cm the color model used to represent pixel values
068 * @param pix a byte array of pixel values
069 * @param off the offset into the array at which the first pixel is stored
070 * @param scan the number of array elements that represents a single pixel row
071 */
072 public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
073 int scan)
074 {
075 this(w, h, cm, pix, off, scan, null);
076 }
077
078 /**
079 * Constructs an ImageProducer from memory.
080 *
081 * @param w the image width.
082 * @param h the image height.
083 * @param cm the color model.
084 * @param pix the image data.
085 * @param off the offset to the first pixel in the array.
086 * @param scan the number of array elements from a pixel on one row to the
087 * corresponding pixel on the next row.
088 * @param props image properties (<code>null</code> permitted).
089 */
090 public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
091 int scan, Hashtable<?,?> props)
092 {
093 width = w;
094 height = h;
095 this.cm = cm;
096 offset = off;
097 scansize = scan;
098 this.props = props;
099 int max = ((scansize > width) ? scansize : width);
100 pixelb = pix;
101 }
102
103 /**
104 * Construct an image producer that reads image data from an
105 * integer array.
106 *
107 * @param w width of image
108 * @param h height of image
109 * @param cm the color model used to represent pixel values
110 * @param pix an integer array of pixel values
111 * @param off the offset into the array at which the first pixel is stored
112 * @param scan the number of array elements that represents a single pixel row
113 */
114 public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
115 int scan)
116 {
117 this(w, h, cm, pix, off, scan, null);
118 }
119
120 /**
121 * Constructs an ImageProducer from memory
122 *
123 * @param w the image width.
124 * @param h the image height.
125 * @param cm the color model.
126 * @param pix the image data.
127 * @param off the offset to the first pixel in the array.
128 * @param scan the number of array elements from a pixel on one row to the
129 * corresponding pixel on the next row.
130 * @param props image properties (<code>null</code> permitted).
131 */
132 public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
133 int scan, Hashtable<?,?> props)
134 {
135 width = w;
136 height = h;
137 this.cm = cm;
138 offset = off;
139 scansize = scan;
140 this.props = props;
141 int max = ((scansize > width) ? scansize : width);
142 pixeli = pix;
143 }
144
145 /**
146 * Constructs an ImageProducer from memory using the default RGB ColorModel.
147 *
148 * @param w the image width.
149 * @param h the image height.
150 * @param pix the image data.
151 * @param off the offset to the first pixel in the array.
152 * @param scan the number of array elements from a pixel on one row to the
153 * corresponding pixel on the next row.
154 * @param props image properties (<code>null</code> permitted).
155
156 */
157 public MemoryImageSource(int w, int h, int[] pix, int off, int scan,
158 Hashtable<?,?> props)
159 {
160 this(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
161 }
162
163 /**
164 * Constructs an ImageProducer from memory using the default RGB ColorModel.
165 *
166 * @param w the image width.
167 * @param h the image height.
168 * @param pix the image data.
169 * @param off the offset to the first pixel in the array.
170 * @param scan the number of array elements from a pixel on one row to the
171 * corresponding pixel on the next row.
172 */
173 public MemoryImageSource(int w, int h, int[] pix, int off, int scan)
174 {
175 this(w, h, ColorModel.getRGBdefault(), pix, off, scan, null);
176 }
177
178 /**
179 * Used to register an <code>ImageConsumer</code> with this
180 * <code>ImageProducer</code>.
181 *
182 * @param ic the image consumer.
183 */
184 public synchronized void addConsumer(ImageConsumer ic)
185 {
186 if (consumers.contains(ic))
187 return;
188
189 consumers.addElement(ic);
190 }
191
192 /**
193 * Used to determine if the given <code>ImageConsumer</code> is
194 * already registered with this <code>ImageProducer</code>.
195 *
196 * @param ic the image consumer.
197 */
198 public synchronized boolean isConsumer(ImageConsumer ic)
199 {
200 if (consumers.contains(ic))
201 return true;
202 return false;
203 }
204
205 /**
206 * Used to remove an <code>ImageConsumer</code> from the list of
207 * registered consumers for this <code>ImageProducer</code>.
208 *
209 * @param ic the image consumer.
210 */
211 public synchronized void removeConsumer(ImageConsumer ic)
212 {
213 consumers.removeElement(ic);
214 }
215
216 /**
217 * Used to register an <code>ImageConsumer</code> with this
218 * <code>ImageProducer</code> and then immediately start
219 * reconstruction of the image data to be delivered to all
220 * registered consumers.
221 */
222 public void startProduction(ImageConsumer ic)
223 {
224 if (! (consumers.contains(ic)))
225 consumers.addElement(ic);
226
227 Vector list = (Vector) consumers.clone();
228 for (int i = 0; i < list.size(); i++)
229 {
230 ic = (ImageConsumer) list.elementAt(i);
231 sendPicture(ic);
232 if (animated)
233 ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
234 else
235 ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
236 }
237 }
238
239 /**
240 * Used to register an <code>ImageConsumer</code> with this
241 * <code>ImageProducer</code> and then request that this producer
242 * resend the image data in the order top-down, left-right.
243 *
244 * @param ic the image consumer.
245 */
246 public void requestTopDownLeftRightResend(ImageConsumer ic)
247 {
248 startProduction(ic);
249 }
250
251 /**
252 * Changes a flag to indicate whether this MemoryImageSource supports
253 * animations.
254 *
255 * @param animated A flag indicating whether this class supports animations
256 */
257 public synchronized void setAnimated(boolean animated)
258 {
259 this.animated = animated;
260 }
261
262 /**
263 * A flag to indicate whether or not to send full buffer updates when
264 * sending animation. If this flag is set then full buffers are sent
265 * in the newPixels methods instead of just regions.
266 *
267 * @param fullbuffers a flag indicating whether to send the full buffers
268 */
269 public synchronized void setFullBufferUpdates(boolean fullbuffers)
270 {
271 this.fullbuffers = fullbuffers;
272 }
273
274 /**
275 * Send an animation frame to the image consumers.
276 */
277 public void newPixels()
278 {
279 if (animated == true)
280 {
281 ImageConsumer ic;
282 Vector list = (Vector) consumers.clone();
283 for (int i = 0; i < list.size(); i++)
284 {
285 ic = (ImageConsumer) list.elementAt(i);
286 sendPicture(ic);
287 ic.imageComplete(ImageConsumer.SINGLEFRAME);
288 }
289 }
290 }
291
292 private void sendPicture(ImageConsumer ic)
293 {
294 ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
295 if (props != null)
296 ic.setProperties(props);
297 ic.setDimensions(width, height);
298 ic.setColorModel(cm);
299 if (pixeli != null)
300 ic.setPixels(0, 0, width, height, cm, pixeli, offset, scansize);
301 else
302 ic.setPixels(0, 0, width, height, cm, pixelb, offset, scansize);
303 }
304
305 /**
306 * Send an animation frame to the image consumers containing the specified
307 * pixels unless setFullBufferUpdates is set.
308 *
309 * @param x the x-coordinate.
310 * @param y the y-coordinate.
311 * @param w the width.
312 * @param h the height.
313 */
314 public synchronized void newPixels(int x, int y, int w, int h)
315 {
316 if (animated == true)
317 {
318 if (fullbuffers)
319 newPixels();
320 else
321 {
322 ImageConsumer ic;
323 Vector list = (Vector) consumers.clone();
324 for (int i = 0; i < list.size(); i++)
325 {
326 ic = (ImageConsumer) list.elementAt(i);
327 ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
328 if (props != null)
329 ic.setProperties(props);
330 if (pixeli != null)
331 {
332 int[] pixelbuf = new int[w * h];
333 for (int row = y; row < y + h; row++)
334 System.arraycopy(pixeli, row * scansize + x + offset,
335 pixelbuf, 0, w * h);
336 ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
337 }
338 else
339 {
340 byte[] pixelbuf = new byte[w * h];
341 for (int row = y; row < y + h; row++)
342 System.arraycopy(pixelb, row * scansize + x + offset,
343 pixelbuf, 0, w * h);
344
345 ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
346 }
347 ic.imageComplete(ImageConsumer.SINGLEFRAME);
348 }
349 }
350 }
351 }
352
353 /**
354 * Send an animation frame to the image consumers containing the specified
355 * pixels unless setFullBufferUpdates is set.
356 *
357 * If framenotify is set then a notification is sent when the frame
358 * is sent otherwise no status is sent.
359 *
360 * @param x the x-coordinate.
361 * @param y the y-coordinate.
362 * @param w the width.
363 * @param h the height.
364 * @param framenotify send notification?
365 */
366 public synchronized void newPixels(int x, int y, int w, int h,
367 boolean framenotify)
368 {
369 if (animated == true)
370 {
371 if (fullbuffers)
372 newPixels();
373 else
374 {
375 ImageConsumer ic;
376 Vector list = (Vector) consumers.clone();
377 for (int i = 0; i < list.size(); i++)
378 {
379 ic = (ImageConsumer) list.elementAt(i);
380 ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
381 if (props != null)
382 ic.setProperties(props);
383 if (pixeli != null)
384 {
385 int[] pixelbuf = new int[w * h];
386 for (int row = y; row < y + h; row++)
387 System.arraycopy(pixeli, row * scansize + x + offset,
388 pixelbuf, 0, w * h);
389 ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
390 }
391 else
392 {
393 byte[] pixelbuf = new byte[w * h];
394 for (int row = y; row < y + h; row++)
395 System.arraycopy(pixelb, row * scansize + x + offset,
396 pixelbuf, 0, w * h);
397 ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
398 }
399 if (framenotify == true)
400 ic.imageComplete(ImageConsumer.SINGLEFRAME);
401 }
402 }
403 }
404 }
405
406 public synchronized void newPixels(byte[] newpix, ColorModel newmodel,
407 int offset, int scansize)
408 {
409 pixeli = null;
410 pixelb = newpix;
411 cm = newmodel;
412 this.offset = offset;
413 this.scansize = scansize;
414 if (animated == true)
415 newPixels();
416 }
417
418 public synchronized void newPixels(int[] newpix, ColorModel newmodel,
419 int offset, int scansize)
420 {
421 pixelb = null;
422 pixeli = newpix;
423 cm = newmodel;
424 this.offset = offset;
425 this.scansize = scansize;
426 if (animated == true)
427 newPixels();
428 }
429 }