1 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
5 import org.ibex.util.*;
6 import org.ibex.translators.*;
9 * The in-memory representation of a PNG or GIF image. It is
10 * read-only. It is usually passed to PixelBuffer.drawPicture()
12 * Implementations of the Platform class should return objects
13 * supporting this interface from the createPicture() method. These
14 * implementations may choose to implement caching strategies (for
15 * example, using a Pixmap on X11).
17 public class Picture {
19 public Picture() { this.stream = null; }
20 public Picture(JS r) { this.stream = r; }
21 private static Cache cache = new Cache(100); ///< Picture, keyed by the Stream that loaded them
23 public JS stream = null; ///< the stream we were loaded from
24 public int width = -1; ///< the width of the image
25 public int height = -1; ///< the height of the image
26 public int[] data = null; ///< argb samples
27 public boolean isLoaded = false; ///< true iff the image is fully loaded
29 /** invoked when an image is fully loaded; subclasses can use this to initialize platform-specific constructs */
30 protected void loaded() { isLoaded = true; }
32 /** turns a stream into a Picture.Source and passes it to the callback */
33 public static Picture load(final JS stream, final Scheduler.Task callback) {
34 Picture ret = (Picture)cache.get(stream);
35 if (ret == null) cache.put(stream, ret = Platform.createPicture(stream));
36 final Picture p = ret;
37 if (!ret.isLoaded && callback != null) {
38 final Ibex.Blessing b = Ibex.Blessing.getBlessing(stream);
39 new java.lang.Thread() { public void run() {
40 InputStream in = null;
42 in = b == null ? Stream.getInputStream(stream) : b.getImage();
43 } catch (IOException e) { Log.error(Picture.class, e);
44 } catch (JSExn e) { Log.error(Picture.class, e);
46 if (in == null) { Log.warn(Picture.class, "couldn't load image for stream " + stream.unclone()); return; }
48 PushbackInputStream pbis = new PushbackInputStream(in);
49 int firstByte = pbis.read();
50 if (firstByte == -1) throw new JSExn("empty stream reading image");
51 pbis.unread(firstByte);
52 if ((firstByte & 0xff) == 'G') GIF.load(pbis, p);
53 else if ((firstByte & 0xff) == 137) PNG.load(pbis, p);
54 else if ((firstByte & 0xff) == 0xff) Platform.decodeJPEG(pbis, p);
55 else throw new JSExn("couldn't figure out image type from first byte");
57 Scheduler.add(callback);
58 } catch (Exception e) {
59 Log.info(this, "exception while loading image");