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