1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.graphics.ImageLoader;
14 
15 import java.lang.all;
16 import java.util.Vector;
17 
18 
19 public import org.eclipse.swt.graphics.ImageLoaderListener;
20 public import org.eclipse.swt.graphics.ImageLoaderEvent;
21 public import org.eclipse.swt.graphics.ImageData;
22 
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.internal.Compatibility;
25 import org.eclipse.swt.internal.image.FileFormat;
26 
27 version(Tango){
28 import tango.core.Array;
29 } else { // Phobos
30 }
31 
32 
33 /**
34  * Instances of this class are used to load images from,
35  * and save images to, a file or stream.
36  * <p>
37  * Currently supported image formats are:
38  * </p><ul>
39  * <li>BMP (Windows or OS/2 Bitmap)</li>
40  * <li>ICO (Windows Icon)</li>
41  * <li>JPEG</li>
42  * <li>GIF</li>
43  * <li>PNG</li>
44  * <li>TIFF</li>
45  * </ul>
46  * <code>ImageLoaders</code> can be used to:
47  * <ul>
48  * <li>load/save single images in all formats</li>
49  * <li>load/save multiple images (GIF/ICO/TIFF)</li>
50  * <li>load/save animated GIF images</li>
51  * <li>load interlaced GIF/PNG images</li>
52  * <li>load progressive JPEG images</li>
53  * </ul>
54  *
55  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ImageAnalyzer</a>
56  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
57  */
58 
59 public class ImageLoader {
60 
61     /**
62      * the array of ImageData objects in this ImageLoader.
63      * This array is read in when the load method is called,
64      * and it is written out when the save method is called
65      */
66     public ImageData[] data;
67 
68     /**
69      * the width of the logical screen on which the images
70      * reside, in pixels (this corresponds to the GIF89a
71      * Logical Screen Width value)
72      */
73     public int logicalScreenWidth;
74 
75     /**
76      * the height of the logical screen on which the images
77      * reside, in pixels (this corresponds to the GIF89a
78      * Logical Screen Height value)
79      */
80     public int logicalScreenHeight;
81 
82     /**
83      * the background pixel for the logical screen (this
84      * corresponds to the GIF89a Background Color Index value).
85      * The default is -1 which means 'unspecified background'
86      *
87      */
88     public int backgroundPixel;
89 
90     /**
91      * the number of times to repeat the display of a sequence
92      * of animated images (this corresponds to the commonly-used
93      * GIF application extension for "NETSCAPE 2.0 01").
94      * The default is 1. A value of 0 means 'display repeatedly'
95      */
96     public int repeatCount;
97 
98     /*
99      * the set of ImageLoader event listeners, created on demand
100      */
101     Vector imageLoaderListeners;
102 
103 /**
104  * Construct a new empty ImageLoader.
105  */
106 public this() {
107     imageLoaderListeners = new Vector();
108     reset();
109 }
110 
111 /**
112  * Resets the fields of the ImageLoader, except for the
113  * <code>imageLoaderListeners</code> field.
114  */
115 void reset() {
116     data = null;
117     logicalScreenWidth = 0;
118     logicalScreenHeight = 0;
119     backgroundPixel = -1;
120     repeatCount = 1;
121 }
122 
123 /**
124  * Loads an array of <code>ImageData</code> objects from the
125  * specified input stream. Throws an error if either an error
126  * occurs while loading the images, or if the images are not
127  * of a supported type. Returns the loaded image data array.
128  *
129  * @param stream the input stream to load the images from
130  * @return an array of <code>ImageData</code> objects loaded from the specified input stream
131  *
132  * @exception IllegalArgumentException <ul>
133  *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
134  * </ul>
135  * @exception SWTException <ul>
136  *    <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
137  *    <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data</li>
138  *    <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
139  * </ul>
140  */
141 public ImageData[] load(InputStream stream) {
142     if (stream is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
143     reset();
144     data = FileFormat.load(stream, this);
145     return data;
146 }
147 
148 /**
149  * Loads an array of <code>ImageData</code> objects from the
150  * file with the specified name. Throws an error if either
151  * an error occurs while loading the images, or if the images are
152  * not of a supported type. Returns the loaded image data array.
153  *
154  * @param filename the name of the file to load the images from
155  * @return an array of <code>ImageData</code> objects loaded from the specified file
156  *
157  * @exception IllegalArgumentException <ul>
158  *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
159  * </ul>
160  * @exception SWTException <ul>
161  *    <li>ERROR_IO - if an IO error occurs while reading from the file</li>
162  *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
163  *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
164  * </ul>
165  */
166 public ImageData[] load(String filename) {
167     if (filename is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
168     InputStream stream = null;
169     void close(){
170         try {
171             if( stream !is null ) stream.close();
172         } catch (IOException e) {
173             // Ignore error
174         }
175     }
176     try {
177         stream = Compatibility.newFileInputStream(filename);
178         scope(exit) close();
179 
180         return load(stream);
181     } catch (IOException e) {
182         SWT.error(SWT.ERROR_IO, e);
183     }
184     return null;
185 }
186 
187 /**
188  * Saves the image data in this ImageLoader to the specified stream.
189  * The format parameter can have one of the following values:
190  * <dl>
191  * <dt><code>IMAGE_BMP</code></dt>
192  * <dd>Windows BMP file format, no compression</dd>
193  * <dt><code>IMAGE_BMP_RLE</code></dt>
194  * <dd>Windows BMP file format, RLE compression if appropriate</dd>
195  * <dt><code>IMAGE_GIF</code></dt>
196  * <dd>GIF file format</dd>
197  * <dt><code>IMAGE_ICO</code></dt>
198  * <dd>Windows ICO file format</dd>
199  * <dt><code>IMAGE_JPEG</code></dt>
200  * <dd>JPEG file format</dd>
201  * <dt><code>IMAGE_PNG</code></dt>
202  * <dd>PNG file format</dd>
203  * </dl>
204  *
205  * @param stream the output stream to write the images to
206  * @param format the format to write the images in
207  *
208  * @exception IllegalArgumentException <ul>
209  *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
210  * </ul>
211  * @exception SWTException <ul>
212  *    <li>ERROR_IO - if an IO error occurs while writing to the stream</li>
213  *    <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
214  *    <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
215  * </ul>
216  */
217 public void save(OutputStream stream, int format) {
218     if (stream is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
219     FileFormat.save(stream, format, this);
220 }
221 
222 /**
223  * Saves the image data in this ImageLoader to a file with the specified name.
224  * The format parameter can have one of the following values:
225  * <dl>
226  * <dt><code>IMAGE_BMP</code></dt>
227  * <dd>Windows BMP file format, no compression</dd>
228  * <dt><code>IMAGE_BMP_RLE</code></dt>
229  * <dd>Windows BMP file format, RLE compression if appropriate</dd>
230  * <dt><code>IMAGE_GIF</code></dt>
231  * <dd>GIF file format</dd>
232  * <dt><code>IMAGE_ICO</code></dt>
233  * <dd>Windows ICO file format</dd>
234  * <dt><code>IMAGE_JPEG</code></dt>
235  * <dd>JPEG file format</dd>
236  * <dt><code>IMAGE_PNG</code></dt>
237  * <dd>PNG file format</dd>
238  * </dl>
239  *
240  * @param filename the name of the file to write the images to
241  * @param format the format to write the images in
242  *
243  * @exception IllegalArgumentException <ul>
244  *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
245  * </ul>
246  * @exception SWTException <ul>
247  *    <li>ERROR_IO - if an IO error occurs while writing to the file</li>
248  *    <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
249  *    <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
250  * </ul>
251  */
252 public void save(String filename, int format) {
253     if (filename is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
254     OutputStream stream = null;
255     try {
256         stream = Compatibility.newFileOutputStream(filename);
257     } catch (IOException e) {
258         SWT.error(SWT.ERROR_IO, e);
259     }
260     save(stream, format);
261     try {
262         stream.close();
263     } catch (IOException e) {
264     }
265 }
266 
267 /**
268  * Adds the listener to the collection of listeners who will be
269  * notified when image data is either partially or completely loaded.
270  * <p>
271  * An ImageLoaderListener should be added before invoking
272  * one of the receiver's load methods. The listener's
273  * <code>imageDataLoaded</code> method is called when image
274  * data has been partially loaded, as is supported by interlaced
275  * GIF/PNG or progressive JPEG images.
276  *
277  * @param listener the listener which should be notified
278  *
279  * @exception IllegalArgumentException <ul>
280  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
281  * </ul>
282  *
283  * @see ImageLoaderListener
284  * @see ImageLoaderEvent
285  */
286 public void addImageLoaderListener(ImageLoaderListener listener) {
287     if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
288     imageLoaderListeners.addElement(cast(Object)listener);
289 }
290 
291 /**
292  * Removes the listener from the collection of listeners who will be
293  * notified when image data is either partially or completely loaded.
294  *
295  * @param listener the listener which should no longer be notified
296  *
297  * @exception IllegalArgumentException <ul>
298  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
299  * </ul>
300  *
301  * @see #addImageLoaderListener(ImageLoaderListener)
302  */
303 public void removeImageLoaderListener(ImageLoaderListener listener) {
304     if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
305     if (imageLoaderListeners is null ) return;
306     imageLoaderListeners.removeElement( cast(Object)listener );
307 }
308 
309 /**
310  * Returns <code>true</code> if the receiver has image loader
311  * listeners, and <code>false</code> otherwise.
312  *
313  * @return <code>true</code> if there are <code>ImageLoaderListener</code>s, and <code>false</code> otherwise
314  *
315  * @see #addImageLoaderListener(ImageLoaderListener)
316  * @see #removeImageLoaderListener(ImageLoaderListener)
317  */
318 public bool hasListeners() {
319     if( imageLoaderListeners is null ) return false;
320     return imageLoaderListeners.size() > 0;
321 }
322 
323 /**
324  * Notifies all image loader listeners that an image loader event
325  * has occurred. Pass the specified event object to each listener.
326  *
327  * @param event the <code>ImageLoaderEvent</code> to send to each <code>ImageLoaderListener</code>
328  */
329 public void notifyListeners(ImageLoaderEvent event) {
330     if (!hasListeners()) return;
331     auto size = imageLoaderListeners.size();
332     for (int i = 0; i < size; i++) {
333         ImageLoaderListener listener = cast(ImageLoaderListener) imageLoaderListeners.elementAt(i);
334         listener.imageDataLoaded(event);
335     }
336 }
337 
338 }