3a4fb6e57e710afa3b8167ecaceba0d30876ac71
[org.ibex.core.git] / src / org / xwt / ImageDecoder.java
1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] 
2 package org.xwt;
3 import java.io.*;
4 import org.xwt.js.*;
5 import org.xwt.util.*;
6 import org.xwt.translators.*;
7
8 /** Interface implemented by classes capable of decoding an image file into an int[] */
9 public abstract class ImageDecoder {
10     
11     /** returns the width of the image */
12     public abstract int getWidth();
13
14     /** returns the height of the image */
15     public abstract int getHeight();
16
17     /** returns the data of the image, as an array of 32-bit AARRGGBB samples */
18     public abstract int[] getData();
19
20     /** loads the image described by string str, possibly blocking for a network load */
21     public static ImageDecoder getImageDecoder(String str, final JS.Callable callback) {
22
23         if (str.indexOf(':') == -1) {
24             String s = str;
25             byte[] b = Resources.getResource(Resources.resolve(s + ".png", null));
26             if (b != null) return PNG.decode(new ByteArrayInputStream(b), str);
27             b = Resources.getResource(Resources.resolve(s + ".jpeg", null));
28             if (b != null) return Platform.decodeJPEG(new ByteArrayInputStream(b), str);
29             return null;
30             
31         } else {
32             java.lang.Thread thread = java.lang.Thread.currentThread();
33             if (!(thread instanceof ThreadMessage)) {
34                 if (Log.on) Log.log(Box.class, "HTTP images can not be loaded from the foreground thread");
35                 return null;
36             }
37             // FIXME: use primitives here
38             ThreadMessage mythread = (ThreadMessage)thread;
39             mythread.setPriority(java.lang.Thread.MIN_PRIORITY);
40             mythread.done.release();
41             try {
42                 HTTP http = new HTTP(str);
43                 final HTTP.HTTPInputStream in = http.GET();
44                 final int contentLength = in.getContentLength();
45                 InputStream is = new FilterInputStream(in) {
46                         int bytesDownloaded = 0;
47                         boolean clear = true;
48                         public int read() throws IOException {
49                             bytesDownloaded++;
50                             return super.read();
51                         }
52                         public int read(byte[] b, int off, int len) throws IOException {
53                             int ret = super.read(b, off, len);
54                             if (ret != -1) bytesDownloaded += ret;
55                             if (clear && callback != null) {
56                                 clear = false;
57                                 ThreadMessage.newthread(new JS.Callable() {
58                                         public Object call(JS.Array args_) throws JS.Exn {
59                                             try {
60                                                 JS.Array args = new JS.Array();
61                                                 args.addElement(new Double(bytesDownloaded));
62                                                 args.addElement(new Double(contentLength));
63                                                 callback.call(args);
64                                             } finally {
65                                                 clear = true;
66                                             }
67                                             return null;
68                                         }
69                                     });
70                             }
71                             return ret;
72                         }
73                     };
74
75                 if (str.endsWith(".gif")) return GIF.decode(is, str);
76                 else if (str.endsWith(".jpeg") || str.endsWith(".jpg")) return Platform.decodeJPEG(is, str);
77                 else return PNG.decode(is, str);
78
79             } catch (IOException e) {
80                 if (Log.on) Log.log(Box.class, "error while trying to load an image from " + str);
81                 if (Log.on) Log.log(Box.class, e);
82                 return null;
83
84             } finally {
85                 MessageQueue.add(mythread);
86                 mythread.setPriority(java.lang.Thread.NORM_PRIORITY);
87                 mythread.go.block();
88             }
89         }
90     }
91
92     /** gets an Image using getImage(), adds it to the cache, and creates a Picture from it */
93     public static Picture getPicture(String os) {
94         Picture ret = null;
95         ret = (Picture)pictureCache.get(os);
96         if (ret != null) return ret;
97         ImageDecoder id = ImageDecoder.getImageDecoder(os, null);
98         if (id == null) return null;
99         ret = Platform.createPicture(id);
100         pictureCache.put(os, ret);
101         imageToNameMap.put(ret, os);
102         return ret;
103     }
104
105     /** caches images, keyed on resource name or url */
106     public static Hash pictureCache = new Hash();
107
108     /** stores image names, keyed on image object */
109     static Hash imageToNameMap = new Hash();
110
111 }