View Javadoc
1   /*
2    * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.awt.image;
27  
28  import java.util.Hashtable;
29  import java.awt.image.ImageConsumer;
30  import java.awt.image.ImageProducer;
31  import java.awt.image.Raster;
32  import java.awt.image.WritableRaster;
33  import java.awt.image.ColorModel;
34  import java.awt.image.IndexColorModel;
35  import java.awt.image.DirectColorModel;
36  import java.awt.image.BufferedImage;
37  import java.awt.image.DataBuffer;
38  
39  public class OffScreenImageSource implements ImageProducer {
40      BufferedImage image;
41      int width;
42      int height;
43      Hashtable properties;
44  
45      public OffScreenImageSource(BufferedImage image,
46                                  Hashtable properties) {
47          this.image = image;
48          if (properties != null) {
49              this.properties = properties;
50          } else {
51              this.properties = new Hashtable();
52          }
53          width  = image.getWidth();
54          height = image.getHeight();
55      }
56  
57      public OffScreenImageSource(BufferedImage image) {
58          this(image, null);
59      }
60  
61      // We can only have one consumer since we immediately return the data...
62      private ImageConsumer theConsumer;
63  
64      public synchronized void addConsumer(ImageConsumer ic) {
65          theConsumer = ic;
66          produce();
67      }
68  
69      public synchronized boolean isConsumer(ImageConsumer ic) {
70          return (ic == theConsumer);
71      }
72  
73      public synchronized void removeConsumer(ImageConsumer ic) {
74          if (theConsumer == ic) {
75              theConsumer = null;
76          }
77      }
78  
79      public void startProduction(ImageConsumer ic) {
80          addConsumer(ic);
81      }
82  
83      public void requestTopDownLeftRightResend(ImageConsumer ic) {
84      }
85  
86      private void sendPixels() {
87          ColorModel cm = image.getColorModel();
88          WritableRaster raster = image.getRaster();
89          int numDataElements = raster.getNumDataElements();
90          int dataType = raster.getDataBuffer().getDataType();
91          int[] scanline = new int[width*numDataElements];
92          boolean needToCvt = true;
93  
94          if (cm instanceof IndexColorModel) {
95              byte[] pixels = new byte[width];
96              theConsumer.setColorModel(cm);
97  
98              if (raster instanceof ByteComponentRaster) {
99                  needToCvt = false;
100                 for (int y=0; y < height; y++) {
101                     raster.getDataElements(0, y, width, 1, pixels);
102                     theConsumer.setPixels(0, y, width, 1, cm, pixels, 0,
103                                           width);
104                 }
105             }
106             else if (raster instanceof BytePackedRaster) {
107                 needToCvt = false;
108                 // Binary image.  Need to unpack it
109                 for (int y=0; y < height; y++) {
110                     raster.getPixels(0, y, width, 1, scanline);
111                     for (int x=0; x < width; x++) {
112                         pixels[x] = (byte) scanline[x];
113                     }
114                     theConsumer.setPixels(0, y, width, 1, cm, pixels, 0,
115                                           width);
116                 }
117             }
118             else if (dataType == DataBuffer.TYPE_SHORT ||
119                      dataType == DataBuffer.TYPE_INT)
120             {
121                 // Probably a short or int "GRAY" image
122                 needToCvt = false;
123                 for (int y=0; y < height; y++) {
124                     raster.getPixels(0, y, width, 1, scanline);
125                     theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
126                                           width);
127                 }
128             }
129         }
130         else if (cm instanceof DirectColorModel) {
131             theConsumer.setColorModel(cm);
132             needToCvt = false;
133             switch (dataType) {
134             case DataBuffer.TYPE_INT:
135                 for (int y=0; y < height; y++) {
136                     raster.getDataElements(0, y, width, 1, scanline);
137                     theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
138                                           width);
139                 }
140                 break;
141             case DataBuffer.TYPE_BYTE:
142                 byte[] bscanline = new byte[width];
143                 for (int y=0; y < height; y++) {
144                     raster.getDataElements(0, y, width, 1, bscanline);
145                     for (int x=0; x < width; x++) {
146                         scanline[x] = bscanline[x]&0xff;
147                     }
148                     theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
149                                           width);
150                 }
151                 break;
152             case DataBuffer.TYPE_USHORT:
153                 short[] sscanline = new short[width];
154                 for (int y=0; y < height; y++) {
155                     raster.getDataElements(0, y, width, 1, sscanline);
156                     for (int x=0; x < width; x++) {
157                         scanline[x] = sscanline[x]&0xffff;
158                     }
159                     theConsumer.setPixels(0, y, width, 1, cm, scanline, 0,
160                                           width);
161                 }
162                 break;
163             default:
164                 needToCvt = true;
165             }
166         }
167 
168         if (needToCvt) {
169             // REMIND: Need to add other types of CMs here
170             ColorModel newcm = ColorModel.getRGBdefault();
171             theConsumer.setColorModel(newcm);
172 
173             for (int y=0; y < height; y++) {
174                 for (int x=0; x < width; x++) {
175                     scanline[x] = image.getRGB(x, y);
176                 }
177                 theConsumer.setPixels(0, y, width, 1, newcm, scanline, 0,
178                                       width);
179             }
180         }
181     }
182 
183     private void produce() {
184         try {
185             theConsumer.setDimensions(image.getWidth(), image.getHeight());
186             theConsumer.setProperties(properties);
187             sendPixels();
188             theConsumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
189             theConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
190         } catch (NullPointerException e) {
191             if (theConsumer != null) {
192                 theConsumer.imageComplete(ImageConsumer.IMAGEERROR);
193             }
194         }
195     }
196 }