1. /*
  2. * @(#)RenderableImageProducer.java 1.8 00/02/02
  3. *
  4. * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. /* ********************************************************************
  11. **********************************************************************
  12. **********************************************************************
  13. *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
  14. *** As an unpublished work pursuant to Title 17 of the United ***
  15. *** States Code. All rights reserved. ***
  16. **********************************************************************
  17. **********************************************************************
  18. **********************************************************************/
  19. package java.awt.image.renderable;
  20. import java.awt.color.ColorSpace;
  21. import java.awt.image.ColorModel;
  22. import java.awt.image.DataBuffer;
  23. import java.awt.image.DirectColorModel;
  24. import java.awt.image.ImageConsumer;
  25. import java.awt.image.ImageProducer;
  26. import java.awt.image.Raster;
  27. import java.awt.image.RenderedImage;
  28. import java.awt.image.SampleModel;
  29. import java.util.Enumeration;
  30. import java.util.Vector;
  31. /**
  32. * An adapter class that implements ImageProducer to allow the
  33. * asynchronous production of a RenderableImage. The size of the
  34. * ImageConsumer is determined by the scale factor of the usr2dev
  35. * transform in the RenderContext. If the RenderContext is null, the
  36. * default rendering of the RenderableImage is used. This class
  37. * implements an asynchronous production that produces the image in
  38. * one thread at one resolution. This class may be subclassed to
  39. * implement versions that will render the image using several
  40. * threads. These threads could render either the same image at
  41. * progressively better quality, or different sections of the image at
  42. * a single resolution.
  43. */
  44. public class RenderableImageProducer implements ImageProducer, Runnable {
  45. /** The RenderableImage source for the producer. */
  46. RenderableImage rdblImage;
  47. /** The RenderContext to use for producing the image. */
  48. RenderContext rc;
  49. /** A Vector of image consumers. */
  50. Vector ics = new Vector();
  51. /**
  52. * Constructs a new RenderableImageProducer from a RenderableImage
  53. * and a RenderContext.
  54. *
  55. * @param rdblImage the RenderableImage to be rendered.
  56. * @param rc the RenderContext to use for producing the pixels.
  57. */
  58. public RenderableImageProducer(RenderableImage rdblImage,
  59. RenderContext rc) {
  60. this.rdblImage = rdblImage;
  61. this.rc = rc;
  62. }
  63. /**
  64. * Sets a new RenderContext to use for the next startProduction() call.
  65. *
  66. * @param rc the new RenderContext.
  67. */
  68. public synchronized void setRenderContext(RenderContext rc) {
  69. this.rc = rc;
  70. }
  71. /**
  72. * Adds an ImageConsumer to the list of consumers interested in
  73. * data for this image.
  74. *
  75. * @param ic an ImageConsumer to be added to the interest list.
  76. */
  77. public synchronized void addConsumer(ImageConsumer ic) {
  78. if (!ics.contains(ic)) {
  79. ics.addElement(ic);
  80. }
  81. }
  82. /**
  83. * Determine if an ImageConsumer is on the list of consumers
  84. * currently interested in data for this image.
  85. *
  86. * @param ic the ImageConsumer to be checked.
  87. * @return true if the ImageConsumer is on the list; false otherwise.
  88. */
  89. public synchronized boolean isConsumer(ImageConsumer ic) {
  90. return ics.contains(ic);
  91. }
  92. /**
  93. * Remove an ImageConsumer from the list of consumers interested in
  94. * data for this image.
  95. *
  96. * @param ic the ImageConsumer to be removed.
  97. */
  98. public synchronized void removeConsumer(ImageConsumer ic) {
  99. ics.removeElement(ic);
  100. }
  101. /**
  102. * Adds an ImageConsumer to the list of consumers interested in
  103. * data for this image, and immediately starts delivery of the
  104. * image data through the ImageConsumer interface.
  105. *
  106. * @param ic the ImageConsumer to be added to the list of consumers.
  107. */
  108. public synchronized void startProduction(ImageConsumer ic) {
  109. addConsumer(ic);
  110. // Need to build a runnable object for the Thread.
  111. Thread thread = new Thread(this, "RenderableImageProducer Thread");
  112. thread.start();
  113. }
  114. /**
  115. * Requests that a given ImageConsumer have the image data delivered
  116. * one more time in top-down, left-right order.
  117. *
  118. * @param ic the ImageConsumer requesting the resend.
  119. */
  120. public void requestTopDownLeftRightResend(ImageConsumer ic) {
  121. // So far, all pixels are already sent in TDLR order
  122. }
  123. /**
  124. * The runnable method for this class. This will produce an image using
  125. * the current RenderableImage and RenderContext and send it to all the
  126. * ImageConsumer currently registered with this class.
  127. */
  128. public void run() {
  129. // First get the rendered image
  130. RenderedImage rdrdImage;
  131. if (rc != null) {
  132. rdrdImage = rdblImage.createRendering(rc);
  133. } else {
  134. rdrdImage = rdblImage.createDefaultRendering();
  135. }
  136. // And its ColorModel
  137. ColorModel colorModel = rdrdImage.getColorModel();
  138. Raster raster = rdrdImage.getData();
  139. SampleModel sampleModel = raster.getSampleModel();
  140. DataBuffer dataBuffer = raster.getDataBuffer();
  141. if (colorModel == null) {
  142. colorModel = ColorModel.getRGBdefault();
  143. }
  144. int minX = raster.getMinX();
  145. int minY = raster.getMinY();
  146. int width = raster.getWidth();
  147. int height = raster.getHeight();
  148. Enumeration icList;
  149. ImageConsumer ic;
  150. // Set up the ImageConsumers
  151. icList = ics.elements();
  152. while (icList.hasMoreElements()) {
  153. ic = (ImageConsumer)icList.nextElement();
  154. ic.setDimensions(width,height);
  155. ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
  156. ImageConsumer.COMPLETESCANLINES |
  157. ImageConsumer.SINGLEPASS |
  158. ImageConsumer.SINGLEFRAME);
  159. }
  160. // Get RGB pixels from the raster scanline by scanline and
  161. // send to consumers.
  162. int pix[] = new int[width];
  163. int i,j;
  164. int numBands = sampleModel.getNumBands();
  165. int tmpPixel[] = new int[numBands];
  166. for (j = 0; j < height; j++) {
  167. for(i = 0; i < width; i++) {
  168. sampleModel.getPixel(i, j, tmpPixel, dataBuffer);
  169. pix[i] = colorModel.getDataElement(tmpPixel, 0);
  170. }
  171. // Now send the scanline to the Consumers
  172. icList = ics.elements();
  173. while (icList.hasMoreElements()) {
  174. ic = (ImageConsumer)icList.nextElement();
  175. ic.setPixels(0, j, width, 1, colorModel, pix, 0, width);
  176. }
  177. }
  178. // Now tell the consumers we're done.
  179. icList = ics.elements();
  180. while (icList.hasMoreElements()) {
  181. ic = (ImageConsumer)icList.nextElement();
  182. ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
  183. }
  184. }
  185. }