| /* |
| * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* ******************************************************************** |
| ********************************************************************** |
| ********************************************************************** |
| *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** |
| *** As an unpublished work pursuant to Title 17 of the United *** |
| *** States Code. All rights reserved. *** |
| ********************************************************************** |
| ********************************************************************** |
| **********************************************************************/ |
| |
| package java.awt.image.renderable; |
| |
| import sun.misc.ManagedLocalsThread; |
| |
| import java.awt.image.ColorModel; |
| import java.awt.image.DataBuffer; |
| import java.awt.image.ImageConsumer; |
| import java.awt.image.ImageProducer; |
| import java.awt.image.Raster; |
| import java.awt.image.RenderedImage; |
| import java.awt.image.SampleModel; |
| import java.util.Enumeration; |
| import java.util.Vector; |
| |
| /** |
| * An adapter class that implements ImageProducer to allow the |
| * asynchronous production of a RenderableImage. The size of the |
| * ImageConsumer is determined by the scale factor of the usr2dev |
| * transform in the RenderContext. If the RenderContext is null, the |
| * default rendering of the RenderableImage is used. This class |
| * implements an asynchronous production that produces the image in |
| * one thread at one resolution. This class may be subclassed to |
| * implement versions that will render the image using several |
| * threads. These threads could render either the same image at |
| * progressively better quality, or different sections of the image at |
| * a single resolution. |
| */ |
| public class RenderableImageProducer implements ImageProducer, Runnable { |
| |
| /** The RenderableImage source for the producer. */ |
| RenderableImage rdblImage; |
| |
| /** The RenderContext to use for producing the image. */ |
| RenderContext rc; |
| |
| /** A Vector of image consumers. */ |
| Vector<ImageConsumer> ics = new Vector<>(); |
| |
| /** |
| * Constructs a new RenderableImageProducer from a RenderableImage |
| * and a RenderContext. |
| * |
| * @param rdblImage the RenderableImage to be rendered. |
| * @param rc the RenderContext to use for producing the pixels. |
| */ |
| public RenderableImageProducer(RenderableImage rdblImage, |
| RenderContext rc) { |
| this.rdblImage = rdblImage; |
| this.rc = rc; |
| } |
| |
| /** |
| * Sets a new RenderContext to use for the next startProduction() call. |
| * |
| * @param rc the new RenderContext. |
| */ |
| public synchronized void setRenderContext(RenderContext rc) { |
| this.rc = rc; |
| } |
| |
| /** |
| * Adds an ImageConsumer to the list of consumers interested in |
| * data for this image. |
| * |
| * @param ic an ImageConsumer to be added to the interest list. |
| */ |
| public synchronized void addConsumer(ImageConsumer ic) { |
| if (!ics.contains(ic)) { |
| ics.addElement(ic); |
| } |
| } |
| |
| /** |
| * Determine if an ImageConsumer is on the list of consumers |
| * currently interested in data for this image. |
| * |
| * @param ic the ImageConsumer to be checked. |
| * @return true if the ImageConsumer is on the list; false otherwise. |
| */ |
| public synchronized boolean isConsumer(ImageConsumer ic) { |
| return ics.contains(ic); |
| } |
| |
| /** |
| * Remove an ImageConsumer from the list of consumers interested in |
| * data for this image. |
| * |
| * @param ic the ImageConsumer to be removed. |
| */ |
| public synchronized void removeConsumer(ImageConsumer ic) { |
| ics.removeElement(ic); |
| } |
| |
| /** |
| * Adds an ImageConsumer to the list of consumers interested in |
| * data for this image, and immediately starts delivery of the |
| * image data through the ImageConsumer interface. |
| * |
| * @param ic the ImageConsumer to be added to the list of consumers. |
| */ |
| public synchronized void startProduction(ImageConsumer ic) { |
| addConsumer(ic); |
| // Need to build a runnable object for the Thread. |
| String name = "RenderableImageProducer Thread"; |
| Thread thread = new ManagedLocalsThread(this, name); |
| thread.start(); |
| } |
| |
| /** |
| * Requests that a given ImageConsumer have the image data delivered |
| * one more time in top-down, left-right order. |
| * |
| * @param ic the ImageConsumer requesting the resend. |
| */ |
| public void requestTopDownLeftRightResend(ImageConsumer ic) { |
| // So far, all pixels are already sent in TDLR order |
| } |
| |
| /** |
| * The runnable method for this class. This will produce an image using |
| * the current RenderableImage and RenderContext and send it to all the |
| * ImageConsumer currently registered with this class. |
| */ |
| public void run() { |
| // First get the rendered image |
| RenderedImage rdrdImage; |
| if (rc != null) { |
| rdrdImage = rdblImage.createRendering(rc); |
| } else { |
| rdrdImage = rdblImage.createDefaultRendering(); |
| } |
| |
| // And its ColorModel |
| ColorModel colorModel = rdrdImage.getColorModel(); |
| Raster raster = rdrdImage.getData(); |
| SampleModel sampleModel = raster.getSampleModel(); |
| DataBuffer dataBuffer = raster.getDataBuffer(); |
| |
| if (colorModel == null) { |
| colorModel = ColorModel.getRGBdefault(); |
| } |
| int minX = raster.getMinX(); |
| int minY = raster.getMinY(); |
| int width = raster.getWidth(); |
| int height = raster.getHeight(); |
| |
| Enumeration<ImageConsumer> icList; |
| ImageConsumer ic; |
| // Set up the ImageConsumers |
| icList = ics.elements(); |
| while (icList.hasMoreElements()) { |
| ic = icList.nextElement(); |
| ic.setDimensions(width,height); |
| ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT | |
| ImageConsumer.COMPLETESCANLINES | |
| ImageConsumer.SINGLEPASS | |
| ImageConsumer.SINGLEFRAME); |
| } |
| |
| // Get RGB pixels from the raster scanline by scanline and |
| // send to consumers. |
| int pix[] = new int[width]; |
| int i,j; |
| int numBands = sampleModel.getNumBands(); |
| int tmpPixel[] = new int[numBands]; |
| for (j = 0; j < height; j++) { |
| for(i = 0; i < width; i++) { |
| sampleModel.getPixel(i, j, tmpPixel, dataBuffer); |
| pix[i] = colorModel.getDataElement(tmpPixel, 0); |
| } |
| // Now send the scanline to the Consumers |
| icList = ics.elements(); |
| while (icList.hasMoreElements()) { |
| ic = icList.nextElement(); |
| ic.setPixels(0, j, width, 1, colorModel, pix, 0, width); |
| } |
| } |
| |
| // Now tell the consumers we're done. |
| icList = ics.elements(); |
| while (icList.hasMoreElements()) { |
| ic = icList.nextElement(); |
| ic.imageComplete(ImageConsumer.STATICIMAGEDONE); |
| } |
| } |
| } |