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 }