001: /*
002: * Copyright (c) 2007, Sun Microsystems, Inc.
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * * Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in
012: * the documentation and/or other materials provided with the distribution.
013: * * Neither the name of Sun Microsystems, Inc. nor the names of its
014: * contributors may be used to endorse or promote products derived
015: * from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
023: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package marsroverviewer;
031:
032: import org.jdesktop.application.Application;
033: import org.jdesktop.application.Task;
034: import java.awt.image.BufferedImage;
035: import java.io.IOException;
036: import java.net.URL;
037: import java.util.Iterator;
038: import java.util.concurrent.TimeUnit;
039: import java.util.logging.Level;
040: import java.util.logging.Logger;
041: import javax.imageio.ImageIO;
042: import javax.imageio.ImageReader;
043: import javax.imageio.event.IIOReadProgressListener;
044: import javax.imageio.stream.ImageInputStream;
045:
046: /**
047: * A Task that loads an image from a URL. Loading and decoding
048: * progress is reported via the Task <code>progress</code> property
049: * and messages are generated when the Task begins and when it
050: * finishes. If errors occur then warnings are logged and the
051: * Task's value is null.
052: * <p>
053: * Applications would typically use LoadImageTask by creating
054: * a private subclass that overrode the <code>done</code> method.
055: * See SingleFrameExample5.java for an example.
056: * <p>
057: * Resources for this class are in the
058: * <code>resources/LoadImageTask.properties</code> ResourceBundle.
059: *
060: */
061: public class LoadImageTask extends Task<BufferedImage, Void> {
062: private static Logger logger = Logger.getLogger(LoadImageTask.class
063: .getName());
064: private final URL url;
065: private ImageReader imageReader = null;
066:
067: public LoadImageTask(Application app, URL url) {
068: super (app, "LoadImageTask"); // init title/description/messages
069: this .url = url;
070: }
071:
072: protected final URL getImageURL() {
073: return url;
074: }
075:
076: @Override
077: protected BufferedImage doInBackground() {
078: IIOReadProgressListener rpl = new IIOReadProgressAdapter() {
079: public void imageProgress(ImageReader r, float p) {
080: setProgress(p, 0.0f, 100.0f);
081: }
082: };
083: message("startedLoadingImage", url);
084: imageReader = findImageReader(url);
085: return loadImage(imageReader, rpl);
086: }
087:
088: private void completionMessage(String resourceKey) {
089: message(resourceKey, url,
090: getExecutionDuration(TimeUnit.MILLISECONDS));
091: }
092:
093: @Override
094: protected void cancelled() {
095: if (imageReader != null) {
096: imageReader.abort();
097: }
098: completionMessage("cancelledLoadingImage");
099: }
100:
101: @Override
102: protected void interrupted(InterruptedException e) {
103: if (imageReader != null) {
104: imageReader.abort();
105: }
106: completionMessage("cancelledLoadingImage");
107: }
108:
109: @Override
110: protected void succeeded(BufferedImage image) {
111: completionMessage("finishedLoadingImage");
112: }
113:
114: @Override
115: protected void failed(Throwable e) {
116: completionMessage("failedLoadingImage");
117: }
118:
119: @Override
120: protected void finished() {
121: imageReader = null;
122: }
123:
124: /* The methods below are what's required by the Java imaging
125: * API to enable tracking the progress of an ImageIO read()
126: * and optionally aborting it. If we weren't interested in
127: * tracking image-loading progress or supporting Task.cancel()
128: * it would be enough to just use ImageIO.read().
129: */
130: private ImageReader findImageReader(URL url) {
131: ImageInputStream input = null;
132: try {
133: input = ImageIO.createImageInputStream(url.openStream());
134: } catch (IOException e) {
135: logger.log(Level.WARNING, "bad image URL " + url, e);
136: }
137: ImageReader reader = null;
138: if (input != null) {
139: Iterator readers = ImageIO.getImageReaders(input);
140: while ((reader == null) && (readers != null)
141: && readers.hasNext()) {
142: reader = (ImageReader) readers.next();
143: }
144: reader.setInput(input);
145: }
146: return reader;
147: }
148:
149: private BufferedImage loadImage(ImageReader reader,
150: IIOReadProgressListener listener) {
151: BufferedImage image = null;
152: try {
153: if (listener != null) {
154: reader.addIIOReadProgressListener(listener);
155: }
156: int index = reader.getMinIndex();
157: image = reader.read(index);
158: } catch (IOException e) {
159: logger.log(Level.WARNING, "loadImage failed", e);
160: } finally {
161: ImageInputStream input = (ImageInputStream) (reader
162: .getInput());
163: if (input != null) {
164: try {
165: input.close();
166: } catch (IOException e) {
167: }
168: }
169: if (reader != null) {
170: reader.removeAllIIOReadProgressListeners();
171: reader.dispose();
172: }
173: }
174: return image;
175: }
176:
177: /* Makes creating an IIOReadProgressListener less horrible looking; see
178: * LoadImageTask.doInBackground() above.
179: */
180: private static class IIOReadProgressAdapter implements
181: IIOReadProgressListener {
182: public void imageStarted(ImageReader rdr, int imageIndex) {
183: }
184:
185: public void imageProgress(ImageReader rdr, float percentageDone) {
186: }
187:
188: public void imageComplete(ImageReader rdr) {
189: }
190:
191: public void readAborted(ImageReader rdr) {
192: }
193:
194: public void sequenceStarted(ImageReader rdr, int minIndex) {
195: }
196:
197: public void sequenceComplete(ImageReader rdr) {
198: }
199:
200: public void thumbnailStarted(ImageReader rdr, int imageIndex,
201: int thumbIndex) {
202: }
203:
204: public void thumbnailProgress(ImageReader rdr,
205: float percentageDone) {
206: }
207:
208: public void thumbnailComplete(ImageReader rdr) {
209: }
210: }
211: }
|