001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Oleg V. Khaschansky
019: * @version $Revision$
020: */package org.apache.harmony.awt.gl.image;
021:
022: import java.awt.image.ColorModel;
023: import java.awt.image.ImageConsumer;
024: import java.io.BufferedInputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.security.AccessController;
028: import java.security.PrivilegedAction;
029: import java.util.ConcurrentModificationException;
030: import java.util.Hashtable;
031: import java.util.Iterator;
032: import java.util.List;
033:
034: /**
035: * This class contains common functionality for all image decoders.
036: */
037: abstract class ImageDecoder {
038: private static final int MAX_BYTES_IN_SIGNATURE = 8;
039:
040: List<ImageConsumer> consumers;
041: InputStream inputStream;
042: DecodingImageSource src;
043:
044: boolean terminated;
045:
046: /**
047: * Chooses appropriate image decoder by looking into input stream and checking
048: * the image signature.
049: * @param src - image producer, required for passing data to it from the
050: * created decoder via callbacks
051: * @param is - stream
052: * @return decoder
053: */
054: static ImageDecoder createDecoder(DecodingImageSource src,
055: InputStream is) {
056: InputStream markable;
057:
058: if (!is.markSupported()) {
059: markable = new BufferedInputStream(is);
060: } else {
061: markable = is;
062: }
063:
064: // Read the signature from the stream and then reset it back
065: try {
066: markable.mark(MAX_BYTES_IN_SIGNATURE);
067:
068: byte[] signature = new byte[MAX_BYTES_IN_SIGNATURE];
069: markable.read(signature, 0, MAX_BYTES_IN_SIGNATURE);
070: markable.reset();
071:
072: if ((signature[0] & 0xFF) == 0xFF
073: && (signature[1] & 0xFF) == 0xD8
074: && (signature[2] & 0xFF) == 0xFF) { // JPEG
075: return new JpegDecoder(src, is);
076: } else if ((signature[0] & 0xFF) == 0x47 && // G
077: (signature[1] & 0xFF) == 0x49 && // I
078: (signature[2] & 0xFF) == 0x46) { // F
079: return new GifDecoder(src, is);
080: } else if ((signature[0] & 0xFF) == 137
081: && // PNG signature: 137 80 78 71 13 10 26 10
082: (signature[1] & 0xFF) == 80
083: && (signature[2] & 0xFF) == 78
084: && (signature[3] & 0xFF) == 71
085: && (signature[4] & 0xFF) == 13
086: && (signature[5] & 0xFF) == 10
087: && (signature[6] & 0xFF) == 26
088: && (signature[7] & 0xFF) == 10) {
089: return new PngDecoder(src, is);
090: }
091: } catch (IOException e) { // Silently
092: }
093:
094: return null;
095: }
096:
097: ImageDecoder(DecodingImageSource _src, InputStream is) {
098: src = _src;
099: consumers = src.consumers;
100: inputStream = is;
101: }
102:
103: public abstract void decodeImage() throws IOException;
104:
105: public synchronized void closeStream() {
106: if (inputStream != null) {
107: try {
108: inputStream.close();
109: } catch (IOException e) {
110: }
111: }
112: }
113:
114: /**
115: * Used when all consumers are removed and there's no more need to
116: * run the decoder.
117: */
118: public void terminate() {
119: src.lockDecoder(this );
120: closeStream();
121: terminated = true;
122: }
123:
124: protected void setDimensions(int w, int h) {
125: if (terminated) {
126: return;
127: }
128:
129: for (ImageConsumer ic : consumers) {
130: ic.setDimensions(w, h);
131: }
132: }
133:
134: protected void setProperties(Hashtable<?, ?> props) {
135: if (terminated) {
136: return;
137: }
138:
139: for (ImageConsumer ic : consumers) {
140: ic.setProperties(props);
141: }
142: }
143:
144: protected void setColorModel(ColorModel cm) {
145: if (terminated) {
146: return;
147: }
148:
149: for (ImageConsumer ic : consumers) {
150: ic.setColorModel(cm);
151: }
152: }
153:
154: protected void setHints(int hints) {
155: if (terminated) {
156: return;
157: }
158:
159: for (ImageConsumer ic : consumers) {
160: ic.setHints(hints);
161: }
162: }
163:
164: protected void setPixels(int x, int y, int w, int h,
165: ColorModel model, byte pix[], int off, int scansize) {
166: if (terminated) {
167: return;
168: }
169:
170: src.lockDecoder(this );
171:
172: for (ImageConsumer ic : consumers) {
173: ic.setPixels(x, y, w, h, model, pix, off, scansize);
174: }
175: }
176:
177: protected void setPixels(int x, int y, int w, int h,
178: ColorModel model, int pix[], int off, int scansize) {
179: if (terminated) {
180: return;
181: }
182:
183: src.lockDecoder(this );
184:
185: for (ImageConsumer ic : consumers) {
186: ic.setPixels(x, y, w, h, model, pix, off, scansize);
187: }
188: }
189:
190: protected void imageComplete(int status) {
191: if (terminated) {
192: return;
193: }
194:
195: src.lockDecoder(this );
196:
197: ImageConsumer ic = null;
198:
199: for (Iterator<ImageConsumer> i = consumers.iterator(); i
200: .hasNext();) {
201: try {
202: ic = i.next();
203: } catch (ConcurrentModificationException e) {
204: i = consumers.iterator();
205: continue;
206: }
207: ic.imageComplete(status);
208: }
209: }
210:
211: }
|