1 /*******************************************************************************
2 * Copyright (c) 2000, 2016 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.graphics;
20 import org.eclipse.swt.*;
21 import org.eclipse.swt.internal.image.*;
24 * Instances of this class are used to load images from,
25 * and save images to, a file or stream.
27 * Currently supported image formats are:
29 * <li>BMP (Windows or OS/2 Bitmap)</li>
30 * <li>ICO (Windows Icon)</li>
36 * <code>ImageLoaders</code> can be used to:
38 * <li>load/save single images in all formats</li>
39 * <li>load/save multiple images (GIF/ICO/TIFF)</li>
40 * <li>load/save animated GIF images</li>
41 * <li>load interlaced GIF/PNG images</li>
42 * <li>load progressive JPEG images</li>
46 * NOTE: <code>ImageLoader</code> is implemented in Java on some platforms, which has
47 * certain performance implications. Performance and memory sensitive applications may
48 * benefit from using one of the constructors provided by <code>Image</code>, as these
49 * are implemented natively.</p>
51 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ImageAnalyzer</a>
52 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
54 public class ImageLoader {
57 * the array of ImageData objects in this ImageLoader.
58 * This array is read in when the load method is called,
59 * and it is written out when the save method is called
61 public ImageData[] data;
64 * the width of the logical screen on which the images
65 * reside, in pixels (this corresponds to the GIF89a
66 * Logical Screen Width value)
68 public int logicalScreenWidth;
71 * the height of the logical screen on which the images
72 * reside, in pixels (this corresponds to the GIF89a
73 * Logical Screen Height value)
75 public int logicalScreenHeight;
78 * the background pixel for the logical screen (this
79 * corresponds to the GIF89a Background Color Index value).
80 * The default is -1 which means 'unspecified background'
83 public int backgroundPixel;
86 * the number of times to repeat the display of a sequence
87 * of animated images (this corresponds to the commonly-used
88 * GIF application extension for "NETSCAPE 2.0 01").
89 * The default is 1. A value of 0 means 'display repeatedly'
91 public int repeatCount;
94 * This is the compression used when saving jpeg and png files.
96 * When saving jpeg files, the value is from 1 to 100,
97 * where 1 is very high compression but low quality, and 100 is
98 * no compression and high quality; default is 75.
100 * When saving png files, the value is from 0 to 3, but they do not impact the quality
101 * because PNG is lossless compression. 0 is uncompressed, 1 is low compression and fast,
102 * 2 is default compression, and 3 is high compression but slow.
107 public int compression;
110 * the set of ImageLoader event listeners, created on demand
112 List<ImageLoaderListener> imageLoaderListeners;
115 * Construct a new empty ImageLoader.
117 public ImageLoader() {
122 * Resets the fields of the ImageLoader, except for the
123 * <code>imageLoaderListeners</code> field.
127 logicalScreenWidth = 0;
128 logicalScreenHeight = 0;
129 backgroundPixel = -1;
135 * Loads an array of <code>ImageData</code> objects from the
136 * specified input stream. Throws an error if either an error
137 * occurs while loading the images, or if the images are not
138 * of a supported type. Returns the loaded image data array.
140 * @param stream the input stream to load the images from
141 * @return an array of <code>ImageData</code> objects loaded from the specified input stream
143 * @exception IllegalArgumentException <ul>
144 * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
146 * @exception SWTException <ul>
147 * <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
148 * <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data</li>
149 * <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
152 public ImageData[] load(InputStream stream) {
153 if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
155 data = FileFormat.load(stream, this);
160 * Loads an array of <code>ImageData</code> objects from the
161 * file with the specified name. Throws an error if either
162 * an error occurs while loading the images, or if the images are
163 * not of a supported type. Returns the loaded image data array.
165 * @param filename the name of the file to load the images from
166 * @return an array of <code>ImageData</code> objects loaded from the specified file
168 * @exception IllegalArgumentException <ul>
169 * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
171 * @exception SWTException <ul>
172 * <li>ERROR_IO - if an IO error occurs while reading from the file</li>
173 * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
174 * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
177 public ImageData[] load(String filename) {
178 if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
179 InputStream stream = null;
181 stream = new FileInputStream(filename);
183 } catch (IOException e) {
184 SWT.error(SWT.ERROR_IO, e);
187 if (stream != null) stream.close();
188 } catch (IOException e) {
196 * Saves the image data in this ImageLoader to the specified stream.
197 * The format parameter can have one of the following values:
199 * <dt><code>IMAGE_BMP</code></dt>
200 * <dd>Windows BMP file format, no compression</dd>
201 * <dt><code>IMAGE_BMP_RLE</code></dt>
202 * <dd>Windows BMP file format, RLE compression if appropriate</dd>
203 * <dt><code>IMAGE_GIF</code></dt>
204 * <dd>GIF file format</dd>
205 * <dt><code>IMAGE_ICO</code></dt>
206 * <dd>Windows ICO file format</dd>
207 * <dt><code>IMAGE_JPEG</code></dt>
208 * <dd>JPEG file format</dd>
209 * <dt><code>IMAGE_PNG</code></dt>
210 * <dd>PNG file format</dd>
213 * @param stream the output stream to write the images to
214 * @param format the format to write the images in
216 * @exception IllegalArgumentException <ul>
217 * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
219 * @exception SWTException <ul>
220 * <li>ERROR_IO - if an IO error occurs while writing to the stream</li>
221 * <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
222 * <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
225 public void save(OutputStream stream, int format) {
226 if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
227 FileFormat.save(stream, format, this);
231 * Saves the image data in this ImageLoader to a file with the specified name.
232 * The format parameter can have one of the following values:
234 * <dt><code>IMAGE_BMP</code></dt>
235 * <dd>Windows BMP file format, no compression</dd>
236 * <dt><code>IMAGE_BMP_RLE</code></dt>
237 * <dd>Windows BMP file format, RLE compression if appropriate</dd>
238 * <dt><code>IMAGE_GIF</code></dt>
239 * <dd>GIF file format</dd>
240 * <dt><code>IMAGE_ICO</code></dt>
241 * <dd>Windows ICO file format</dd>
242 * <dt><code>IMAGE_JPEG</code></dt>
243 * <dd>JPEG file format</dd>
244 * <dt><code>IMAGE_PNG</code></dt>
245 * <dd>PNG file format</dd>
248 * @param filename the name of the file to write the images to
249 * @param format the format to write the images in
251 * @exception IllegalArgumentException <ul>
252 * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
254 * @exception SWTException <ul>
255 * <li>ERROR_IO - if an IO error occurs while writing to the file</li>
256 * <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
257 * <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
260 public void save(String filename, int format) {
261 if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
262 OutputStream stream = null;
264 stream = new FileOutputStream(filename);
265 } catch (IOException e) {
266 SWT.error(SWT.ERROR_IO, e);
268 save(stream, format);
271 } catch (IOException e) {
276 * Adds the listener to the collection of listeners who will be
277 * notified when image data is either partially or completely loaded.
279 * An ImageLoaderListener should be added before invoking
280 * one of the receiver's load methods. The listener's
281 * <code>imageDataLoaded</code> method is called when image
282 * data has been partially loaded, as is supported by interlaced
283 * GIF/PNG or progressive JPEG images.
285 * @param listener the listener which should be notified
287 * @exception IllegalArgumentException <ul>
288 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
291 * @see ImageLoaderListener
292 * @see ImageLoaderEvent
294 public void addImageLoaderListener(ImageLoaderListener listener) {
295 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
296 if (imageLoaderListeners == null) {
297 imageLoaderListeners = new ArrayList<>();
299 imageLoaderListeners.add(listener);
303 * Removes the listener from the collection of listeners who will be
304 * notified when image data is either partially or completely loaded.
306 * @param listener the listener which should no longer be notified
308 * @exception IllegalArgumentException <ul>
309 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
312 * @see #addImageLoaderListener(ImageLoaderListener)
314 public void removeImageLoaderListener(ImageLoaderListener listener) {
315 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
316 if (imageLoaderListeners == null) return;
317 imageLoaderListeners.remove(listener);
321 * Returns <code>true</code> if the receiver has image loader
322 * listeners, and <code>false</code> otherwise.
324 * @return <code>true</code> if there are <code>ImageLoaderListener</code>s, and <code>false</code> otherwise
326 * @see #addImageLoaderListener(ImageLoaderListener)
327 * @see #removeImageLoaderListener(ImageLoaderListener)
329 public boolean hasListeners() {
330 return imageLoaderListeners != null && imageLoaderListeners.size() > 0;
334 * Notifies all image loader listeners that an image loader event
335 * has occurred. Pass the specified event object to each listener.
337 * @param event the <code>ImageLoaderEvent</code> to send to each <code>ImageLoaderListener</code>
339 public void notifyListeners(ImageLoaderEvent event) {
340 if (!hasListeners()) return;
341 int size = imageLoaderListeners.size();
342 for (int i = 0; i < size; i++) {
343 ImageLoaderListener listener = imageLoaderListeners.get(i);
344 listener.imageDataLoaded(event);