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<String, Object>(); 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 }