Frames | No Frames |
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: }