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 }