Source for java.awt.image.MemoryImageSource

   1: /* MemoryImageSource.java -- Java class for providing image data
   2:    Copyright (C) 1999, 2004, 2006,  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.util.Hashtable;
  42: import java.util.Vector;
  43: 
  44: /**
  45:  * An image producer that delivers image data from an array.
  46:  */
  47: public class MemoryImageSource implements ImageProducer
  48: {
  49:   private boolean animated = false;
  50:   private boolean fullbuffers = false;
  51:   private int[] pixeli;
  52:   private int width;
  53:   private int height;
  54:   private int offset;
  55:   private int scansize;
  56:   private byte[] pixelb;
  57:   private ColorModel cm;
  58:   private Hashtable props = new Hashtable();
  59:   private Vector consumers = new Vector();
  60: 
  61:   /**
  62:    * Construct an image producer that reads image data from a byte
  63:    * array.
  64:    *
  65:    * @param w width of image
  66:    * @param h height of image
  67:    * @param cm the color model used to represent pixel values
  68:    * @param pix a byte array of pixel values
  69:    * @param off the offset into the array at which the first pixel is stored
  70:    * @param scan the number of array elements that represents a single pixel row
  71:    */
  72:   public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
  73:                            int scan)
  74:   {
  75:     this(w, h, cm, pix, off, scan, null);
  76:   }
  77: 
  78:   /**
  79:    * Constructs an ImageProducer from memory.
  80:    *
  81:    * @param w  the image width.
  82:    * @param h  the image height.
  83:    * @param cm  the color model.
  84:    * @param pix  the image data.
  85:    * @param off  the offset to the first pixel in the array.
  86:    * @param scan  the number of array elements from a pixel on one row to the
  87:    *     corresponding pixel on the next row.
  88:    * @param props  image properties (<code>null</code> permitted).
  89:    */
  90:   public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
  91:                            int scan, Hashtable<?,?> props)
  92:   {
  93:     width = w;
  94:     height = h;
  95:     this.cm = cm;
  96:     offset = off;
  97:     scansize = scan;
  98:     this.props = props;
  99:     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: }